I have created a sample Android application just to see the "Google Cast" button on Action Bar and a list of ChromeCast devices when I press it. I did everything according to "Android Sender App Development" document. Now I do see my ChromeCast device when we are on same WiFi, but if I switch on my phone to another WIFi, I don't see my ChromeCast as a "nearby device". I did turned on a flag "Supports Google Cast Guest Mode" on "Google Cast SDK Developer console" for my application. What I am missing?
Here is the code in my activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_main);
mMediaRouter = MediaRouter.getInstance(getApplicationContext());
mMediaRouteSelector = new MediaRouteSelector.Builder()
.addControlCategory(CastMediaControlIntent.categoryForCast(MY_APP_ID))
.build();
}
#Override
protected void onResume() {
super.onResume();
mMediaRouterCallback = new MyMediaRouterCallback();
mMediaRouter.addCallback(mMediaRouteSelector, mMediaRouterCallback,
MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY);
}
#Override
protected void onPause() {
if (isFinishing())
mMediaRouter.removeCallback(mMediaRouterCallback);
super.onPause();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.cast, menu);
MenuItem mediaRouteMenuItem = menu.findItem(R.id.media_route_menu_item);
MediaRouteActionProvider mediaRouteActionProvider = (MediaRouteActionProvider) MenuItemCompat
.getActionProvider(mediaRouteMenuItem);
mediaRouteActionProvider.setRouteSelector(mMediaRouteSelector);
return true;
}
It turns out that the guest mode only works if the application is published.
I published my app (code above) and it started to show the ChromeCast button in both WiFi and guest mode.
Related
I've been developing an app in a Marshmallow 6.0 phone. Today, I ran it in a Nougat 7.0 phone and everything was ok. Changed one line of xml code ('selectableItemBackground' to 'selectableItemBackgroundBorderless' in a LinearLayout) and got an NPE on an unrelated MenuItem ("Attempt to invoke interface method 'android.view.MenuItem android.view.MenuItem.setIcon(int)' on a null object reference") here:
public void updateSpeakerIcon() {
if (mIsSpeakerOn) {
mSpeakerIcon.setIcon(R.drawable.speaker);
setVolumeControlStream(AudioManager.STREAM_MUSIC);
} else {
mSpeakerIcon.setIcon(R.drawable.earphone);
setVolumeControlStream(AudioManager.STREAM_VOICE_CALL);
}
}
I'm using a ViewPager; this method is declared in the activity that contains it; the fragments call this method in their onResume callback.
mSpeakerIcon is 'found' in the onCreateOptionsMenu callback, in the same activity:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.qmenu, menu);
mSpeakerIcon = menu.findItem(R.id.toggle_speaker);
return true;
}
I've changed the one line back to what it was but, of course, it did not fix the problem. Ran the app once again in the 6.0 device and there's no error.
Any ideas? Thanks in advance!
This is in my layout :
<android.support.v7.app.MediaRouteButton
android:id="#+id/button_fling"
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:background="#drawable/mr_ic_media_route_holo_light"
android:layout_height="wrap_content"
android:mediaRouteTypes="user"
android:layout_weight="1"
android:visibility="visible" />
and this in my my activity:
#Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
mMediaRouter = MediaRouter.getInstance(getApplicationContext());
mMediaRouteSelector = new MediaRouteSelector.Builder()
.addControlCategory(CastMediaControlIntent.categoryForCast(getString(R.string.app_id)))
.build();
mMediaRouterCallback = new MyMediaRouterCallback();
mMediaRouteButton = (MediaRouteButton) findViewById(R.id.button_fling);
mMediaRouteButton.setRouteSelector(mMediaRouteSelector);
button_fling2 = (ImageView)findViewById(R.id.button_fling2);
}
public class MyMediaRouterCallback extends MediaRouter.Callback {
public int mRouteCount =0;
#Override
public void onRouteAdded(MediaRouter router, RouteInfo route) {
Log.d(TAG, "onRouteAdded");
if (++mRouteCount == 1) {
// Show the button when a device is discovered.
Log.i(TAG,"MediaRoute is visible");
button_fling2.setVisibility(View.VISIBLE);
mMediaRouteButton.setVisibility(View.VISIBLE);
}
}
#Override
public void onRouteRemoved(MediaRouter router, RouteInfo route) {
Log.d(TAG, "onRouteRemoved");
if (--mRouteCount == 0) {
// Hide the button if there are no devices discovered.
Log.i(TAG,"MediaRoute is GONE");
button_fling2.setVisibility(View.GONE);
mMediaRouteButton.setVisibility(View.GONE);
}
}
}
ButtonFling2 is an ImageView I am using to test MyMediaRouterCallback is working or not. It successfully hides/shows the imageView. However for button_fling(which is a mediaRouteButton instance) does not show anything. It's as if it can't find the resources of the MediaRouteButton so it is showing no cast icon... anyone ever fix this or come across this?
I don't get any errors it just simply does not show, but the logs show that it is visible and the ImageView i have for testing shows up.
AFter fiddling around with this thing, I was able to get the media Router button to show up. I am not entirely sure what I did but I did verify the appid and tried to use my whitelisted app id. I reinstalled the support library. THANK YOU ALL FOR WHO HELPED ON THIS!
I am not 100% sure how this happened but I hope that this helps someone figure out or at least get past this. ActionBar Activity and non action bar activities show the media router button now!!! :)
Implementing onRouteChanged() callback instead of onRouteAdded() should fix the issue.
Example code:
// for MediaRouterButtonActivity
#Override
public void onRouteChanged(MediaRouter router, RouteInfo route) {
if (++mRouteCount == 1) {
// Show the button when a device is discovered.
mMediaRouteButton.setVisibility(View.VISIBLE);
}
}
My goal is to support a functionality that mute phone (possibly with vibrations enabled/disabled), so when a call or sms is received it won't make noise
unmute phone but prompt for "password for unmute".
And this remains valid for any other application, that it ask for password entry before unmute...
How can I do this? What permissions are required in AndroidManifest?
Previously on Stackoverflow, Android mute/unmute phone.
Those answers discuss both permissions and the coding. Also, tasker can handle everything you're looking to do.
And here's a link to a tutorial.
The code below runs fine in the emulator. When you run it, you can see the mute goes on in the notification area. In addition to the code, I had to add the (uses) permission for android.permission.MODIFY_AUDIO_SETTINGS.
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
AudioManager audio = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE);
audio.setRingerMode(AudioManager.RINGER_MODE_SILENT);
return true;
}
I know that Wifi Direct works by creating a Soft AP (software access point) in one of the devices. I also know that many Androids support Wifi Direct, but iPhones do not.
My question is: is it possible to create a device-to-device wifi link that is Wifi Direct on the Android side, but regular wifi on the iPhone side? Where the Android's Wifi Direct would be presenting a soft AP, which the iPhone would see as indistinguishable from a regular AP and be able to associate to.
Imagine that this is out in the wilderness where no router AP is available. Also, neither user has a tethering plan.
This link would be used by a Bump-like app to transfer files.
Depending on your phone you can just set up your Android phone as a portable hotspot and connect to that with the iPhone. From there it would be application specific to get data transferred.
However you can also use the Androids WiFi-Direct libraries. In that case you would use them to set up the Android phone to create a "Group owner", which basically is the same as it being a portable hotspot. Check out:
http://developer.android.com/guide/topics/connectivity/wifip2p.html
I'll give you a code example to help you get started.
public class WifiDirectAPtestActivity extends Activity
{
private WifiP2pManager manager;
private boolean isWifiP2pEnabled = false;
private boolean retryChannel = false;
private final IntentFilter intentFilter = new IntentFilter();
private Channel channel;
private BroadcastReceiver receiver = null;
public void setIsWifiP2pEnabled(boolean isWifiP2pEnabled) {
this.isWifiP2pEnabled = isWifiP2pEnabled;
}
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// add necessary intent values to be matched.
intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
intentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
channel = manager.initialize(this, getMainLooper(), null);
}
/** register the BroadcastReceiver with the intent values to be matched */
#Override
public void onResume() {
super.onResume();
receiver = new WiFiDirectBroadcastReceiver(manager, channel, this);
registerReceiver(receiver, intentFilter);
createGroup();
}
#Override
public void onPause() {
super.onPause();
unregisterReceiver(receiver);
manager.removeGroup(channel, new ActionListener() {
#Override
public void onFailure(int reasonCode) {
Log.d("WifiDirectAptestActivity", "Disconnect failed. Reason :" + reasonCode);
}
#Override
public void onSuccess() {
Log.d("WifiDirectAptestActivity", "Should have been sucessfully removed");
}
});
}
public void createGroup()
{
manager.createGroup(channel, new ActionListener() {
#Override
public void onSuccess() {
// WiFiDirectBroadcastReceiver will notify us. Ignore for now.
Log.d("WifiDirectAPtestActivity", "Group creating request successfully send");
}
#Override
public void onFailure(int reason) {
Toast.makeText(WifiDirectAPtestActivity.this, "Connect failed. Retry.",
Toast.LENGTH_SHORT).show();
}
});
}
In addition you'll need the broadcast receiver, look at the WiFi-Direct demo and it should be clear to you.
Note that line manager.createGroup(channel, new ActionListener() is the codeline of interest, it is this line that actually sets up the device as a portable hotspot.
Hope this clarifies things, I don't really know how detailed explanation you need. Comment if some things are not clear.
In the Android app that I'm working on, I'd like to be able to detect when a new status bar notification appears, regardless of if it was caused by my app. To be more specific, I want to count the number of notifications in a given time frame.
Is this even possible, and if so, how?
Actually, it is possible, I use it in my app.
For Android 4.2 and below:
You need to register an AccessibilityService and make sure the user enables the service.
Example for a service:
public class InstantMessenger extends AccessibilityService {
#Override
public void onAccessibilityEvent(AccessibilityEvent event) {
if (event.getEventType() == AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED) {
//Do something, eg getting packagename
final String packagename = String.valueOf(event.getPackageName());
}
}
#Override
protected void onServiceConnected() {
if (isInit) {
return;
}
AccessibilityServiceInfo info = new AccessibilityServiceInfo();
info.eventTypes = AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED;
info.feedbackType = AccessibilityServiceInfo.FEEDBACK_SPOKEN;
setServiceInfo(info);
isInit = true;
}
#Override
public void onInterrupt() {
isInit = false;
}
}
Example for checking if your Service is activated
For Android 4.3 and above:
Use the Notification Listener API
The new Notification Listener API in Android 4.3 enables you to do this.
With this there is less need for the accessibility hack. It also allows you to dismiss notifications.