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.
Related
TLDR; Run a method that updates the UI on a dedicated thread from a OnCallBack function that is updated every few milliseconds!!
I'm getting a live stream video using Vitamio library and displaying it on a SurfaceView This is done by the MediaPlayer of the library.
However, I need to split the screen for VR experience. If MediaPlayer had a method to display the video on 2 SurfaceViews then I would not have had such a problem. Unfortunately, it doesn't.
Therefore, I figured that the live stream video runs on the SurfaceView in first half of the screen and I display each frame image Bitmap to an ImageView which occupies the second half of the screen.
This is working but not good... The problem is that copying the image is too much work and that's why the ImageView is laggy.
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<SurfaceView
android:id="#+id/surfaceview_livestream"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginBottom="#dimen/activity_vertical_margin"
android:layout_marginTop="#dimen/activity_vertical_margin"
android:layout_weight="1" />
<ImageView
android:id="#+id/imageview_livestream"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginBottom="#dimen/activity_vertical_margin"
android:layout_marginTop="#dimen/activity_vertical_margin"
android:layout_weight="1"
android:contentDescription="#string/live_stream" />
</LinearLayout>
public class LiveStreamManager implements MediaPlayer.OnBufferingUpdate {
// some irrelevant code
public void initLiveStream() {
io.vov.vitamio.MediaPlayer mediaPlayer = new io.vov.vitamio.MediaPlayer();
mediaPlayer.setDisplay(mainActivity.getSurfaceView());
// other irrelevant code...
}
#Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
Bitmap frame = mp.getCurrentFrame();
if (frame != null) {
mainActivity.setFrame(frame);
}
}
}
public MainActivity extends Activity {
// some code...
// I want this to run on a dedicated thread
public void setFrame(Bitmap frame) {
imageviewLiveStream.setImageBitmap(frame);
}
}
try using rxJava:
Observable.interval(100, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.handlerThread())
.map(t -> {
// do rendering here (on single render thread
return 'rendered images'
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe( t -> {
// set bitmaps here
});
Rendering will be one on separate thread (create scheduler in advance ) every 10 milliseconds, then results will be processed on main thread.
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 ;-)
My question is more from the design point of view, related to the Material design philosophy.
So do all newest apps now completely rely on the swipe to refresh UX pattern when it's possible to apply it (e.g. map activities cannot have it because they take over the swipe gesture)? Is it considered too "old-school" to put a refresh icon in the Toolbar (in the way that this ActionBar in the picture has it)?
Because my app shows realtime statistics to the user and I would like to be sure that 90% of the users will instantly know how to refresh them.
You can replace it with SwipeRefreshLayout.
add this to your xml file:
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/refreshLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ListView
android:id="#+id/mList"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.v4.widget.SwipeRefreshLayout>
and to you java file this:
SwipeRefreshLayout mRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.refreshLayout);
handler.postDelayed(refreshing, 100);
mRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
// YOUR TASK HERE.
}
});
EDIT:
To make user know that there's an refresh in your app you can use this to make it refresh automatically everytime app opens:
private Handler handler = new Handler();
private final Runnable refreshing = new Runnable() {
public void run() {
mRefreshLayout.setRefreshing(true);
try {
if (mRefreshLayout.isRefreshing()) {
// YOUR TASK HERE.
handler.removeCallbacks(this);
} else {
mRefreshLayout.setRefreshing(false);
}
} catch (Exception e) {
Log.e("", e.getMessage(), e);
}
}
};
in your task in onPreExecute() add this:
if (!mRefreshLayout.isRefreshing()) {
mRefreshLayout.setRefreshing(true);
}
and in onPostExecute() add this:
mRefreshLayout.setRefreshing(false);
Don't forget handler.postDelayed(refreshing, 100); after defining the SwipeRefreshLayout view.
https://www.google.de/design/spec/patterns/swipe-to-refresh.html
Alternatively, the manual refresh method requires users to initiate content updates via an action or gesture.
Note: an action or gesture.
The material design guide does not prohibit the button, it simply does not give such an emphasis to it. But if it's an important action for your app, you should certainly use it.
https://www.google.com/design/icons/#ic_refresh
I need to display ProgressBar on button action and also need to update same activity page after successful action. ProgressBar is getting displayed but it hangs (it interrupts and hangs) on action process. Circle bar does not animate.
Code sample : ProgessBar is added in layout xml
<ProgressBar
android:id="#+id/loginProgressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:visibility="invisible"
android:layout_marginTop="100dp" />
Code behind : on button action
public void onClick(View view)
{
if(loginProgressBar ==null)
{
loginProgressBar = (ProgressBar)findViewById(R.id.loginProgressBar);
}
loginProgressBar.setVisibility(View.VISIBLE);
myHandler.post(new Runnable()
{
public void run()
{
Intent intent = new Intent(LoginActivity.this,RegisterActivity.class);
startActivity(intent);
}
});
}
It seems that myHandler is updating main UI and at the same time. ProgressBar is also part of Main UI, so it hangs.
Please provide solution so that ProgressBar works without any interruption.
What you need is an AsyncTask.
Take a look at the example in the link provided, it is exactly what you are looking for !
Hope it helps !
This question has probably been asked a lot many times.. Yes! I am facing the so called "black screen problem"..
My first activity is which the main activity, in which login is done, and this activity is followed by the next one which is a simple summary report of the user's account.
Now, for this report, i fetch the dataset, parse it and use it to build the table dynamically.
The villan black screen appears here!! The report, as in the table is rendered properly, but upon that screen, this black tranluscent layer keeps appearing.
I tried everything, using handlers, asynctask, translucent theme but nothing helps!! The villan still appears when my summary report loads. It goes away if i press the "Back" button, and the screen appears normal, as it is expected to be when it loads the first time.. I cant figure out what exactly is going wrong, whether, its my coding approach(dynamically generating the table) or it is an emulator problem or what.
My emulator details are as follows:
CPU:ARM
Target: Android 2.3.3
skin: WVGA800
sd card:1024M
Someone please rescue me!!
EDIT:
In my Second activity i do the following:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_summary_report);
ad = new AlertDialog.Builder(this).create();
boolean is = IsConnectedToNetwork();
if (is == true){
Handler execWS = new Handler();
execWS.post(callWS);//Fetch Data via web service and parse it
if(result != null){
Handler genUI = new Handler();
genUI.post(createUI);// generate the table based on "result". ie. in a for loop i create textviews and append it to the table layout
}
}
else{
Error = "Connection Failed. Try Again!";
}
if(Error.length() != 0){
ad.setMessage(Error);
ad.setTitle("Error..");
ad.show();
}
}
My Xml layout for the second activity..
<?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:baselineAligned="false"
android:gravity="center"
android:orientation="vertical">
<TableLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dip">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:contentDescription="#string/Logo"
android:src="#drawable/complogo"
android:gravity="top"/>
<TextView
android:id="#+id/lblLoginInfo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center_horizontal"/>
</TableLayout>
<TableLayout
android:id="#+id/tblSummRep"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="4"
android:padding="5dip">
</TableLayout>
<TableLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:padding="5dip">
<TextView
android:id="#+id/AppName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="#string/AppName"
android:textColor="#ff6600" />
<TextView
android:id="#+id/AppVersion"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="#string/AppVersion"
android:textColor="#ff6600" />
<TextView
android:id="#+id/Disclaimer"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/Disclaimer"
android:textColor="#ff6600" />
</TableLayout>
</LinearLayout>
I append the textview to "tblSummRep"..
UPDATE
my asynctask class..
private class ShareWork extends AsyncTask<Void, Void, Boolean>{
ProgressDialog pDlg;
//String[][] result = null;
protected void onPreExecute(){
pDlg.setMessage("Please wait while the Report Loads...");
pDlg.show();
}
#Override
protected Boolean doInBackground(Void... params) {
boolean RetVal = false;
//my fetch code
return RetVal;
}
protected void onPostExecute(Boolean value){
if(value == true){
pDlg.setMessage("Please try again later!!");
pDlg.show();
}
else{
createUI.run();
}
}
}
I do not know what do you refer to by "black screen problem", but you state that you are fetching data (I guess from a remote server) and that happens. That sounds to me about blocking the UI thread. In which method of the activity are you fetching the data (maybe in the onCreate)? You should not perform time-consuming actions on the graphical thread, such as querying a remote server (which could take some seconds). In these cases always an AsyncTask should be used. The user should receive some feedback about what is going on in the background, so using a ProgressBar is normally recommendable (or at least a spinner).
You can take a look about how to solve a similar problem with an AsyncTask here.
Update
You have just posted your code. The problem lies (as I presumed) in this line of code:
execWS.post(callWS);//Fetch Data via web service and parse it
I guess this is a WS call. You are blocking here the UI thread. Create an AsyncTask the same way as the one of the link I provided, and upon completion of the task execute the rest of the code (display error or the dynamic table with the data).
Your AsyncTask could look like this (I have not tried it):
private class LoadTableTask extends AsyncTask<URL, Integer, Object> {
protected Object doInBackground(URL... urls) {
Handler execWS = new Handler();
execWS.post(urls[0]);//Fetch Data via web service and parse it
return result;
}
protected void onProgressUpdate(Integer... progress) {
//Not used in your case. It would be a good idea to create an undefined progress dialog in your case
}
protected void onPostExecute(Object result) {
if(result != null){
Handler genUI = new Handler();
genUI.post(createUI);// generate the table based on "result". ie. in a for loop i create textviews and append it to the table layout
}
}
}
Your onCreate() method would be replaced by:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_summary_report);
ad = new AlertDialog.Builder(this).create();
boolean is = IsConnectedToNetwork();
if (is == true){
new LoadTableTask().execute(callWS);
}
else{
Error = "Connection Failed. Try Again!";
}
if(Error.length() != 0){
ad.setMessage(Error);
ad.setTitle("Error..");
ad.show();
}
}