I am very new to Android SDK so that question may be very simple.
I try to make am app that shows the current time. I know how to get the current time but i somehow need to update the time. So i try putting a while/if statement that updates the time outside onCreate() and inside main Activity class but 4 errors pop up saying "unexpected end of Decleration.
I cant really find a way to solve this so any help would be much appreciated.
I get the idea that a longer example will be more useful for you.
Make a layout for the application, call the file activity_main.xml.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.example.timedemo.MainActivity">
<TextView
android:id="#+id/textClock"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignTop="#+id/textView" />
</LinearLayout>
Make a file called MainActivity.java, make it extends Activity (or something else that extends Activity)
Init your layout in the onCreate method.
Use a handler to run code at a delayed time, instead of halting the thread.
public class MainActivity extends AppCompatActivity {
//Handler can be used to send Runnables (code to run) to a specific Thread.
//In this case the UI-thread.
Handler handler = new Handler();
//TextView variable defined in Class-scope.
TextView myTextClock;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Load the layout from activity_main.xml into this Activity.
setContentView(R.layout.activity_main);
//Find the textclock that is mentioned in the activity_main.xml
//Use the ID to find the right View.
//As you can see in the xml-file, the id is 'textClock'.
//Looks like this in the XML --> <TextView android:id="#+id/textClock" />
myTextClock = (TextView) this.findViewById(R.id.textClock);
//Tell the Handler to execute this code at an interval.
handler.postDelayed(codeToRun, 1000);
}
//The runnable contains the code that will be run every second.
Runnable codeToRun = new Runnable() {
#Override
public void run() {
updateTime();
}
};
public void updateTime(){
//Code to update the Clock on the UI-thread
//see: http://developer.android.com/reference/java/text/SimpleDateFormat.html
DateFormat sdf = DateFormat.getDateTimeInstance();
myTextClock.setText(sdf.format(new Date()));
//Make sure it runs the next time too.
handler.postDelayed(codeToRun, 1000);
}
}
Hope this helps you get on the right path.
I'd suggest you use ScheduledThreadPoolExecutor class instead of a while loop. There is an example in this tutorial on how to create a clock app. It can be useful as a starting point.
class ClockTask implements Runnable {
#Override
public void run() {
updateClock();
}
}
ScheduledThreadPoolExecutor se = new ScheduledThreadPoolExecutor(1);
se.scheduleAtFixedRate(new ClockTask(), 0, 1000, TimeUnit.MICROSECONDS);
I'm not sure how you plan to make this, but keep in mind that you do not stall the Main Thread. So avoid a construction like this:
while(true){ Thread.sleep(1000); updateTime(); }
A better approach would to use Handler, for example:
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
updateTime();
}
}, 1000);
http://developer.android.com/reference/android/os/Handler.html#postDelayed(java.lang.Runnable,%20long)
Hope this helps ;-)
Related
I am trying to build a music player.
I did everything what is required and the working is smooth but however i can't seem to see my MediaController Controls.
Declaration:private MusicController musicController;
public class MusicController extends MediaController {
public MusicController(Context context) {
super(context);
}
#Override
public void hide() {
}
}
MainActivity.java
musicController.setMediaPlayer(this);
musicController.setAnchorView(findViewById(R.id.my_recycler_view));
musicController.setEnabled(true);
mainactivity.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:background="#FF330000"
android:layout_height="match_parent"
android:id="#+id/recycler_parent_view"
>
<android.support.v7.widget.RecyclerView
android:id="#+id/my_recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
I have added a screenshot.
What could be the problem here?
MainActivity.java
MusicService.java
MusicController.java
MyAdaptor.java
I have included every file that might be important. Please help me look out the problem. Thank You.
I see musicController.show(0); being called only after some click events.
Should you call it also soon after having set the anchorView?
From documentation
void show (int timeout)
Show the controller on screen. It will go away automatically after 'timeout' milliseconds of inactivity.
Try just musicController.show();
EDIT
I saw you overrode the MusicController.hide() method so it shouldn't be removed after the timeout period, but still it seems to me you don't show it when you set the anchorView
UPDATE
musicController.setMediaPlayer(this);
musicController.setAnchorView(findViewById(R.id.my_recycler_view));
musicController.setEnabled(true);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
musicController.show();
}
}, 5000);
I ran your code and I was able to show the controller after applying a delay. Maybe you should show it after your service is connected...not sure about this, but at least you could try this code and then improve it.
can any on explain why button is getting displayed.
xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<Button
android:layout_below="#+id/tt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Simple Button"/>
</RelativeLayout>
MainActivity
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), "onCreate", Toast.LENGTH_SHORT).show();
}
}, 10000);
// Looper.loop();
}
}
For above code out put is
For above code out put is (when i uncomment Looper.loop())
can any one explain this. What Looper.loop() is doing to not display the button on ui.
Things i know is Looper is what im using is main ui threads Looper.
i know Looper is already running(looping over the messages) and im calling Looper.loop(); I just want to know what is does that button drawing wont happen on the ui thread means does that Looper get reset or removes some message. exactly what happen when we call Looper.loop() on a thread looper when its already looping.
Looper.loop(); is an infinite loop so when you're running this off the main UI thread, the code execution basically stops there, preventing the UI from being displayed.
Not sure what you're trying to accomplish, and I'm not at all too familiar with Looper and threads but here are a few articles I read about Looper.
http://mindtherobot.com/blog/159/android-guts-intro-to-loopers-and-handlers/
http://corner.squareup.com/2013/10/android-main-thread-1.html
I'm trying to make a simple slideshow that fades out and fades in a few images without a button click. I had found a few examples to assist me, but I am having trouble getting the first image to fade into the second image. As of now, it just fades out and that is it. I have my code below.
fade_in.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#android:anim/linear_interpolator">
<alpha
android:fromAlpha="0.1"
android:toAlpha="1.0"
android:duration="5000"
android:repeatCount="infinite"
/>
</set>
fade_out.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="#android:anim/linear_interpolator">
<alpha
android:fromAlpha="1.0"
android:toAlpha="0.1"
android:duration="5000"
android:repeatCount="infinite"
/>
</set>
layout.xml
<?xml version="1.0" encoding="utf-8"?>
<ViewSwitcher xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/switcher"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:inAnimation="#anim/fade_in"
android:outAnimation="#anim/fade_out" >
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="fitCenter"
android:src="#drawable/image1" />
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="fitCenter"
android:src="#drawable/image2" />
</ViewSwitcher>
MainClass.Activity
public class MainClass extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.next);
slideshow();
}
public void slideshow() {
ViewSwitcher switching = (ViewSwitcher)findViewById(R.id.switcher);
if (switching.getDisplayedChild() == 0) {
switching.showNext();
} else {
switching.showPrevious();
}
}
}
In that case, you need to use a timer. You use it like so:
public class MainClass extends Activity {
private Timer timer;
private ViewSwitcher switching;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.next);
switching = (ViewSwitcher)findViewById(R.id.switcher);
timer = new Timer();
timer.scheduleAtFixedRate(new NextImageTask(), 0, 5000);
//5000 is in milliseconds, meaning 5 seconds
}
public void slideshow() {
if (switching.getDisplayedChild() == 0) {
switching.showNext();
} else {
switching.showPrevious();
}
}
private class NextImageTask extends TimerTask {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
slideshow();
}
});
}
}
}
What does this chunk of code do? Well, let's go at it step by step. First declare the views
private Timer timer;
private ViewSwitcher switching;
And then initialize them in the onCreate method
switching = (ViewSwitcher)findViewById(R.id.switcher);
timer = new Timer();
Then we start the timer! To start a timer and tell it what to do, we do it like so
timer.scheduleAtFixedRate(new NextImageTask(), 0, 5000);
This line of code basically means Hey timer, schedule a task at a fixed rate of 5 seconds. Start immediately!
The first argument is the task to be scheduled, an object, the NextImageTask(). This object contains a Runnable that contains the code to run every interval. The interval is a fixed rate of 5 seconds. In the code however it is written as 5000. This is because the method accepts the third argument as millisecond. To get 5 seconds, we must multiply 5 by 1,000 which results to, yep you guessed it right, 5,000. The timer is asked to start immediately by passing a second argument as 0. This is the delay. If you pass 2000 there, the timer will start after a 2 second delay. Just like the third argument, the method accepts this second argument as millisecond.
Next is the method slideshow() which is the same as the OP. This is what the OP wants to do.
Lastly is the private object, NextImageTask().
private class NextImageTask extends TimerTask {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
slideshow();
}
});
}
}
This is the task that will be done by the timer at the fixed rate/every 5 seconds. It should extend TimerTask for the timer to work properly. TimerTask is an abstract class so the NextImageTask() should implement one method, the run() method. This method should contain the code that the timer will run at a fixed interval. This runs on a different thread so if you need to do something in the UI just like the OP's case, we need to run on the UI thread. This is the reason why we called runOnUiThread here. Finally, inside is another runnable calling the OP's method slideshow().
I have been developing iOS apps for quite a time and now i have switched to android. I have a requirement in which I have to start timer(In think in Android, I need to use handler) when view appears(onResume) and invalidate timer(stop handler) when view disappears(onPause). I am able to create runnable Handler but not able to stop it.
My code is:
protected void AutoRefresh() {
try{
handler.postDelayed(new Runnable() {
public void run() {
new LongOperation().execute("");
}
AutoRefresh();
}, 60000);
}
catch(Exception ex){
}
}
Now, how can I stop this this handler thread when view disappears. Please also comment, if its not the right way to do timer implementation in android.
when view appears(onResume) and invalidate timer(stop handler) when
view disappears(onPause). I am able to create runnable Handler but not
able to stop it.
Keep a reference to the Runnable you use:
private Runnable mRefresh = new Runnable() {
public void run() {
new LongOperation().execute("");
}
AutoRefresh();
}
//...
protected void AutoRefresh() {
handler.postDelayed(mRefresh, 60000);
}
and in onPause remove it like this:
handler.removeCallbacks(mRefresh);
Keep in mind that this will not remove the currently Runnable that is being executed(if any) so in the LongOperation's onPostExecute method you might want to check if the Activity is still available before refreshing the UI or doing any other interaction with the Activity.
Please also comment, if its not the right way to do timer
implementation in android.
You seem to need to do an action at a certain interval of time and using a Handler is the way to do it, I don't think a timer is what you need.
I am new to Android and I am having trouble understanding the concept so basically this is what i want to do to understand it better..
I created a DrawShape class that extends view. In this class in the OnDraw() I am creating a circle and filling it with a color.
From the Activity I am calling the application. //Until this point I am doing fine.
Now, I need to re-paint the Circle multiple times (Blue, Red, Yellow etc..)
So I was reading and the best way is to use Threads.. I also read you need to use postInvalidate() to redraw (I still dont understand from where I should be calling this) is this called from the Activity?, or within the OnDraw()?.
Hopefully you understand what i want to accomplish, is just that i havent found a good tutorial that shows this, how to repaint something x amount of times .. when I do Thread.sleep() it all stops then it shows my app.. but now i understand why, because i am playing with the main Thread.
Please help me understand this..
Thank you
i did something like this
animcolor()
{
Timer timer = new Timer();
int delay = ...;
int period = ...;
timer.schedule(new TimerTask(){
run() {
setColor( randomint() ); )
customview.postInvalidate();
}
}, delay, period);
threads? not necessary to create them; Timers make a good job on concurrency.
... and the code would somewhat look like....
res/layout/file.xml
<org.customviewlayout a:id="#+id/customlayout"/>
src/org.MyActivity.java
class MyActivity
{
onCreate()
{
customlayout = findViewById(R.id.customlayout);
customlayout.animcolor();
}
}
src/org.customlayout.java
import org.customview;
class customlayout
{
customview;
customlayout(context, attrs)
{
customview = new customview();
addview(customview); // so it's onDraw() method will be called
}
onlayout(...)
{
customview.layout(...);
}
animcolor()
{
Timer timer = new Timer();
int delay = ...;
int period = ...;
timer.schedule(new TimerTask(){
run() {
setColor( randomint() ); )
customview.postInvalidate();
}
}, delay, period);
}
setcolor(int)
{
....
}
}
i think, you can do this using a Timer and a TimerTask inside your activity. The TimerTask runs with the delay you specify and when run all you what to do is yourDrawShapeInstance.postInvalidate();
the mechanism is this, because you arent on the ui thread you call postInvalidate() to add an invalidate on the ui queue, when the ui engine pick the delayed invalidate that you invoke before, then calls automatically the onDraw method of your DrawShape view and the view will be redrawed.
(i donĀ“t test this, i write here)
TimerTask task = new TimerTask(){
public void run(){
myDrawShapeInstance.postInvalidate();
}
}
When drawing, always use a thread away from the main thread and always invalidate after thread has finished (for the most part -- to display current results from drawing). You will probably call your drawing functions from some user-related event, so make sure you're making another thread for that drawing process. Follow those rules and you will be fine.
void drawCircleToCanvas(int color)
{
final Handler handler = new Handler() {
public void handleMessage(Message msg) {
myDrawShapeInstance.postInvalidate();
}
};
Thread updateUI = new Thread() {
public void run() {
//************draw something here***************
handler.sendEmptyMessage(0);
}
};
updateUI.start();
}