I've been working from the example applications from Google to prepare our Chromecast capabilities,
What I've found however is that you are required to have a button in the ActionBar (as implemented by Google) in order to get an ActionProvider in order to attach your selector to.
#Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(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(mCaster.getMediaRouteSelector());
return true;
}
Intact, the entire example and API seems to be hot-wired to centre around the use of this button. I'm fine with reproducing the look and feel the Android are trying to go with here - but I use a custom ActionBar in my app which means I don't have any "hooks" to select the route et al.
Does anyone know how to work around this?
To begin with, I suggest you consider moving to appcompat actionbar so you can get all the benefits moving forward out of the box.
That said, the answer to your question is: yes, it is doable if you are willing to do a bit of extra work to manage the lifecycle and states yourself. I outline the steps here so you can create a working example for yourself. The requirements is to have appcompat and mediarouter from v7 support library in your project but you don't need to use any specific type of actionbar or no need to use the MediaRouteButton; in fact you can trigger the discovery and the rest in any shape or form that you want. Here are the steps:
Make sure appcompat and mediarouter from v7 support library are included in your dependencies. It is important to have v7 version of mediarouter
Do the usual thing, i.e. build a CastContext and set the stage ready for discovery (you need to create an instance of MediaRouteAdapter, which I have called myMediaRouteAdapter):
mCastContext = new CastContext(getApplicationContext());
MediaRouteHelper.registerMinimalMediaRouteProvider(mCastContext,
myMediaRouteAdapter);
mMediaRouter = MediaRouter.getInstance(getApplicationContext());
mMediaRouteSelector = MediaRouteHelper
.buildMediaRouteSelector(MediaRouteHelper.CATEGORY_CAST,
"YOUR_APP_NAME", null);
mMediaRouterCallback = new MyMediaRouterCallback();
Start the discovery by calling the following in your, say, onStart():
mMediaRouter.addCallback(mMediaRouteSelector, mMediaRouterCallback,
MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY);
In your custom callback MyMediaRouterCallback, listen for routes as they get added or removed. As routes get discovered, your onRouteAdded() method of your callback will be called and as they go away, the onRouteRemoved() will be called. It will be now your responsibility to hold on to the list of valid routes in your choice of data structure.
Lets say, for the sake of argument, you present the list to users in a dialog (makes sense, doesn't it?) where user sees a the name of route (i.e. device) in the UI and each item represents a RouteInfo. Then when a user clicks on a route, you need to call
mMediaRouter.selectRoute(info);
The above call results in another callback of your custom callback to be called, the onRouteSelected(). In that callback, call the following:
MediaRouteHelper.requestCastDeviceForRoute(info);
Finally, this will call the onDeviceAvailable() callback of the myMediaRouteAdapter and passes a CastDevice to you which you should be able to grab and use. When you are done with a route and want to "deselect" it, call
mMediaRouter.selectRoute(mMediaRouter.getDefaultRoute());
Hopefully that is enough to get you going.
I found better solution:
MediaRouteChooserDialog dialog =new MediaRouteChooserDialog(context);
dialog.setRouteSelector(mediaRouteSelector);
dialog.show();
Shows popup and will call onRouteSelected method on callback.
Related
I created in google sheets a custom menu linked to a custom function that pops up a dialog window with a youtube video in it. All this i did on my PC in a browser.
I now installed google sheets on my android phone, and shared the sheet myself (using a second gmail account). I now notice that the custom menu doesn't appear in google sheets app on android.
I am wondering, does custom menus and dialogs work in google sheets on android. Am i doing something incorrect in relation to permissions -- i.e. are there any permissions i need to assign to other users for them to see and use custom menu items and related functions. If yes, how can i make the correct settings.
thank you,
Dan
i used a drop-down list/combo - populated using data validation. this is supported on mobile device. then i use the onEdit(e) event to trigger the code... the first step is to identify what's been edited (which cell) and then act accordingly... an example follows where the drop-down would contain two items "Do Task 1" and "Do Task 2"... the event is triggered when any cell on the sheet is changed... the process then identifies if the cell change is that of the drop-down (cell value set to a global variable 'FunctionsCell') if it is the drop-down that triggered the event, it then gets the value (see the 'getValue()' part of the code) and then inspects it's value and then executes the code accordingly (see '// do something part')
var FunctionsCell = "B2" // global
function onEdit(e) {
var editCell = e.range.getA1Notation()
switch (editCell) {
case FunctionsCell:
{
var functionType = SpreadsheetApp.getActiveSheet().getRange(FunctionsCell).getValue()
switch(functionType) {
case "Do Task 1": {
// do something
break
}
case "Do Task 2": {
// do something
break
}
}
}
}
}
In a project I have 3 Actors and 5 Use cases.I want to regulate Actors access to entities based on their roles(RBAC).Also all Actors see the same UI,but some UI controls are disabled for each actor according to his/her Role.I can use If statements to decide specific control must be enabled for current Actor or disabled? For example:
If (User.Roles(...))
{
btnEditOrder.enabled = false;
}
That is possible,but UI is complex and each layout has many UI controls.So managing all these possible options and hard-code that logic in the application seems daunting.Specially, number of use cases,actors and their permissions may change later.Do you know how I can avoid hard-code such logic and have a good design?
IMHO it would be good to create separate menu.xml files for each role.
Let's say you make separate menu.xml files namely:
options_menu_manager.xml
options_menu_engineer.xml
options_menu_director.xml
You will need to make a Helper class around it. I am assuming you have the role already in the memory, you can do something like:
class Helper{
public static int getOptionsMenu(){
switch(Global.role){
case Constants.MANAGER:
return R.menu.options_menu_manager.xml;
...
...
}
}
}
and wherever you need to get the menus, you can use a helper function instead of using a R.menu.* file.
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(Helper.getOptionsMenu(), menu);
return true;
}
Although, this is just a way of getting ROLE based menu. You should still have a good background validation of the authorization of all the performed actions. For that also you can create a helper that matches the current user's role against the allowed actions to see if he is allowed to do what he is doing or not.
Beginner here, targetting sdk v14 and v17 for my learning...no need for older support.
I am using the master/detail template and trying to get an action menu (for SEARCH) to show up both in phone and tablet view. Actually I can get it to work, but I have to duplicate up my code in both ItemDetailActivity.java and ItemListActivity.java
These are the methods that I have to have in both for SEARCH to work:
public boolean onQueryTextChange(String newText) {
public boolean onQueryTextSubmit (String query) {
public boolean onClose () {
I only want to search the "detail", not the "list".
So my question: is there a way to associate the action bar with only the list fragment? That way I can keep the search functions in 1 file.
Thanks!
I'll go ahead and answer what I (think) I know as I don't want to leave this question open.
From tracing in the debugger, it looks to me like the phone activity and the tablet activity are separate and if you want to hook up an actionmenu, you have to hook it up to both separately.
Everything I've read about Intents talks about using them to push data, or to start one Activity from another Activity. I want to pull data from an Activity that's already running.
The Tab Layout tutorial at http://developer.android.com/resources/tutorials/views/hello-tabwidget.html illustrates what I want to do. (My app is doing some engineering calculations instead, but the tutorial code provides a good analogy to my app.) The tutorial creates an app with three tabs, and each tab hosts a separate activity.
To expand on the example in the tutorial, suppose I select an artist in the Artists tab/activity. I want to be able to select the Albums tab/activity and have it display all the albums featuring that artist.
It seems to me that I need to use an Intent to do this. All of the tutorials I've found assume that I would create a "See albums" Button in the Artists tab/activity, and that pressing the Button would execute an Intent that starts the Albums activity and passes artistName.
I DO NOT want to create that Button. Real estate on the Artists layout is precious, and I have a perfectly good Albums tab, AND the HelloTabWidget activity already contains an intent to create the Albums tab.
Besides, a user will want to skip back and forth between Album and Artist in order to change artist selections, and the tabs are a perfectly good way to do this. There's no need to complicate the UI with another button.
So how can I have the Albums activity PULL artistName from the Artists activity when the Albums tab is selected (or the Albums layout is displayed), rather than have the Artists activity START Albums and PUSH the artistName?
Equivalents I can think of from other programming worlds:
Global variables. Discouraged in Android devt, right? And if they do exist, what are they called?
A getter, like artistName = Artists.getArtistName(); . I get the feeling that it's not that easy.
Writing to, and reading from, a file - that is, mass storage or non-volatile memory. I don't need the artistName value to be permanent. It will be reset to null every time the user launches the application.
So how is it done in the Android world? Do I use an Intent - and if so, how?
Global variables were the right answer.
I thought Java discouraged their use, but a couple of links that appeared in the "Related" links on the right margin of this window mentioned them directly. One was "Android: How to declare global variables?" and the other was "how to pass value betweeen two tab in android". Both pointed to the Application Class as the place to define global variables and methods. Armed with this new knowledge, I found an article called "Android Application Class" on the Xoriant blog that expanded on the StackOverflow answers.
It's best to review those three links first. I need to add some tips to what those authors have said.
Your Application class has to be in its own separate file. (That might be a "duh" to some people, but not to everybody.) Here's a good framework for an example called Something.java:
public class Something extends Application {
// Put application wide (global) variables here
// Constants are final, so they don't have to be private
// But other variables should be declared private;
// use getters/setters to access them
public final boolean FEET = false;
public final boolean METERS = true;
private boolean units = FEET;
#Override
public void onCreate() {
super.onCreate();
// Put any application wide (global) initialization here
}
// Put application wide (global) methods here
public boolean getUnits() {
return units;
}
public void setUnits(boolean whichOne) {
units = whichOne;
}
}
I'm using Eclipse with the ADT plug-in, in Windows XP. Eclipse doesn't always behave properly if you edit XML code directly, so it's best to open AndroidManifest.xml, then select the Application tab and enter your application name in the Name field. You don't need to put a dot or period in front of the name. Just type in the name of your class, like "Globals" or "MyApplication" or whatever. (Note that this is the default application in your Manifest. You don't have to create a separate <application></application> tag.
This step may not be necessary on an actual Android device, but it was necessary for the emulator: you need to use the getApplicationContext() command in every onCreate() and every method that will be accessing the global variables and methods. I tried to put it outside of onCreate() with the rest of my activity wide variables, and it didn't work. Putting it inside every method seems wasteful, but both the emulator and the Android device work fine with it that way. Here's a sample showing how I used it:
public void fooBar() {
// Access to global variables and methods
final Something s = (Something)getApplicationContext();
// ...
// This next line demonstrates both a global method and a global variable
if (s.getUnits() == s.FEET) {
// do something with feet
} else {
// do something with meters instead
}
// ...
}
Those were the only hiccups I encountered. The three references that I have listed, taken together, are otherwise pretty complete.
I realise this is a specific problem however I feel like others who are dealing with compatibility must have dealt with this.
As the user swipes through various fragments in the ViewPager I would also like the actionBar menu items to change. I am not sure if this is easily doable for the compatibility actionbar, any direction or help would be extremely appreciated. I am changing the title simply via setTitle() since the ActionBarHelper handles this however i cant find anything for updating the menu items. I tried the following but it fails..
public void setMenuDynamically(int resId){
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(resId, menu);
}
Looking through the code it seems there should be an easy/obvious way to get a handle to the SimpleMenu and add an item and set its icon.
Thanks in advance ( I am hoping the google boys are reading this as the android developers Google+ suggests)
Ok well please let me know if I suck as describing things or if there just is not much knowledge on this topic. If the first I am really sorry guys. Regardless I seemed to get this to work but am unsure if this is the correct way.
AcitonBarHelper
public void updateMenu(MenuItem item) {
}
ActionBarHelperBase (for 2.2 - 3.0 devices )
#Override
public void updateMenu(MenuItem item){
addActionItemCompatFromMenuItem(item);
}
And create similar methods for honeycomb and ICS
finally i have a listener for page changing and in that listener i call...
public void setMenuDynamically(int resId, String title){
MenuItem item = menu.add(title);
item.setIcon(resId);
getActionBarHelper().updateMenu(item);
MenuItemCompat.setShowAsAction(item, MenuItemCompat.SHOW_AS_ACTION_ALWAYS);
}
I am not sure if the MenuItemCompat is necessary but I included it nonetheless. Everything seems to work great for 2.2 at least. I will most likely have to make changes in the Overrides but I can handle myself from here.