I'm working on an App where i want to stream a specific video, which is located on my mobile device. I want to stream this video with the help of ChromeCast to a projector. I've done the Google Chromecast Tutorials (https://codelabs.developers.google.com/codelabs/cast-videos-android/#0 for example) and already looked for an answer to my Question but there wasn't the perfect answer to solve my problem in my opinion.
There are a few solutions in other coding languages but not especially for java.
My problem with the Google Cast API is: I want to select my ChromeCast without pressing the Cast Button in the OptionMenu, which appears to select one of the ChromeCasts in the Network.
I just found out, that the setRouteSelector-Methode from the class CastButtonFactory is a part to select the Device. But i can't find out, how to select the device automatically.
Here is my Code where the CastButton appears (created in the OnCreateOptionsMenu-Method)(It's just the Code to Connect to the ChromeCast. I didn't implement the Code for selecting and streaming the video yet):
Can anyone help me?
Code:
public class MainActivity extends AppCompatActivity {
private CastSession mCastSession;
private CastContext mCastContext;
private SessionManager mSessionManager;
private final SessionManagerListener mSessionManagerListener = new SessionManagerListenerImpl();
private class SessionManagerListenerImpl implements SessionManagerListener{
#Override
public void onSessionStarting(Session session) {}
#Override
public void onSessionStarted(Session session, String sessionId) {
invalidateOptionsMenu();
}
#Override
public void onSessionStartFailed(Session session, int i) {}
#Override
public void onSessionEnding(Session session) {}
#Override
public void onSessionEnded(Session session, int error) {
finish();
}
#Override
public void onSessionResuming(Session session, String s) {}
#Override
public void onSessionResumed(Session session, boolean wasSuspended) {
invalidateOptionsMenu();
}
#Override
public void onSessionResumeFailed(Session session, int i) {}
#Override
public void onSessionSuspended(Session session, int i) {}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mCastContext = CastContext.getSharedInstance(this);
mCastContext.registerLifecycleCallbacksBeforeIceCreamSandwich(this, savedInstanceState);
mSessionManager = CastContext.getSharedInstance(this).getSessionManager();
}
#Override
public void onResume(){
mCastSession = mCastContext.getSessionManager().getCurrentCastSession();
mSessionManager.addSessionManagerListener(mSessionManagerListener);
super.onResume();
}
#Override
public void onPause(){
super.onPause();
mSessionManager.removeSessionManagerListener(mSessionManagerListener);
mCastSession = null;
}
#Override
public void onStart(){
super.onStart();
}
#Override public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.menu, menu);
CastButtonFactory.setUpMediaRouteButton(getApplicationContext(),
menu,
R.id.media_route_menu_item);
return true;
}}
This is possible with SDK v2. Check out the source code for MediaRouteChooserDialogFragment, the UI element that lets users select a Cast device. You'll want to create a MediaRouter.Callback, and override onRouteAdded(MediaRouter router, MediaRouter.RouteInfo newRoute). If the new route is not the default route, select it with mMediaRouter.selectRoute(newRoute). This will connect you to the receiver device without any user interaction.
This should work for testing, but please don't do this in a production app. #AliNaddaf correctly notes this is against the UX guidelines and Google Cast terms of service (you can imagine the potential for abuse if apps are permitted to start casting without the user's consent).
Related
I'm trying to implement the saved games codes, I can save and load without problems, all the data is OK. But I when I connect with Google, the code connect with a default account. I try to use account picker and use the returned mail but the account was the same, same data. I need select the account or my code is useless.
This is my connect code:
public static void conectarGoogle(final FragmentActivity a) {
GoogleApiClient.ConnectionCallbacks connectionCallbacks = new GoogleApiClient.ConnectionCallbacks() {
#Override
public void onConnected(#Nullable Bundle bundle) {
Log.d(TAG,"conected");
}
#Override
public void onConnectionSuspended(int i) {
mGoogleApiClient.connect();
}
};
GoogleApiClient.OnConnectionFailedListener cfl = new GoogleApiClient.OnConnectionFailedListener() {
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
Log.d(TAG,"failed="+connectionResult.toString());
mIsResolving = BaseGameUtils.resolveConnectionFailure(a, mGoogleApiClient, connectionResult, RC_SIGN_IN, a.getString(R.string.signin_other_error));
}
};
mGoogleApiClient = new GoogleApiClient.Builder(a)
.addConnectionCallbacks(connectionCallbacks)
.addOnConnectionFailedListener(cfl)
.addApi(Games.API)
.addScope(Games.SCOPE_GAMES)
.addScope(Drive.SCOPE_APPFOLDER)
.setViewForPopups(a.findViewById(android.R.id.content))
.build();
mGoogleApiClient.connect();
}
public static void desconectarGoogle(){
if(mGoogleApiClient!=null && isSignedIn()) {
mGoogleApiClient.disconnect();
}
}
I need help for this problem. I use this code in mainactivity and preferencesactivity and cant select the account for save the progress.
The default account use the marchinglord2524 name.
The Games.API dont left add Auth.GOOGLE_SIGN_IN_API.
(Posted on behalf of the OP).
I don't know why, but I have in my device a default user, I clear the data on my Google Play Services and now I use my user: saved games documentation.
I'm trying to add a custom quick settings tile for my application. I've followed the sample code/documentation from Google but I'm running into some issues. After searching for some time I couldn't find any solutions.
When I run my app, the tile is visible in the quick settings tray, but it remains in an unavailable state.
I need a two-way flow of communication with the tile, i.e., when the user selects the tile, the app responds and when the user does a certain action within the app, the tile UI is toggled.
The problem seems to come from attempting to bind my custom TileService class to my MainActivity -- whenever I bind it is when the tile goes into a consistently unavailable state. I can't seem to figure out why though because it's being bound successfully. If I don't bind it (i.e. just have the one way communication of the tile commanding the app), the tile is active and the app responds to selecting it.
Ultimately I do the binding to attain a reference to my custom TileService class to be able to call it's method toggleTileUI(). I'm not looking to use a singleton or static member variable as a solution to getting a reference to my service.
Here's what I have in my AndroidManifest.xml:
<service
android:name=".ConnectionQuickSettingsService"
android:label="#string/quick_setting_tile_connect"
android:icon="#drawable/tile_icon"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
<intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE" />
</intent-filter>
</service>
Here's my ConnectionQuickSettingsService.java:
#TargetApi(24)
public class ConnectionQuickSettingsService extends TileService {
private static final String TAG = "ConnectionQuickSettingsService";
private final IBinder mBinder = new LocalBinder();
public class LocalBinder extends Binder {
ConnectionQuickSettingsService getService() {
return ConnectionQuickSettingsService.this;
}
}
#Override
public IBinder onBind(Intent i) {
return mBinder;
}
#Override
public void onTileAdded() {
L.d(TAG, "onTileAdded()");
}
#Override
public void onStartListening() {
L.d(TAG, "onStartListening()");
}
#Override
public void onClick() {
L.d(TAG, "Quick Settings tile selected");
toggleInAppSwitch();
toggleTileUI();
}
private void toggleInAppSwitch() {
doStuff();
}
public void toggleTileUI() {
Tile tile = this.getQsTile();
doStuffWithTile();
}
}
and lastly (the relevant parts of) my MainActivity.java:
#Override
protected void onStart() {
super.onStart();
Intent i = new Intent(this, ConnectionQuickSettingsService.class);
bindService(i, mConnection, Context.BIND_AUTO_CREATE);
}
#Override
protected void onStop() {
super.onStop();
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
private ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className,
IBinder service) {
ConnectionQuickSettingsService.LocalBinder binder = (ConnectionQuickSettingsService.LocalBinder) service;
mQSService = binder.getService();
mBound = true;
L.d(TAG, "Bound to QS service successfully");
}
#Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
L.d(TAG, "Disconnected from QS service");
}
};
public void onOnOff(){
L.d(TAG, "On/Off switch toggled");
if (mBound) {
mQSService.toggleTileUI();
}
}
Any input would be greatly appreciated, thanks!
Part of your problem is that you are overriding onBind(), which clobbers the TileService implementation of onBind(), preventing Android from working with your ConnectionQuickSettingsService. I would expect that there would be error messages in LogCat from a system process complaining about this.
The other part of your problem is that you assume that getQsTile() works at arbitrary points in time. It doesn't.
I recommend finding some other interaction pattern with your tile, such as using META_DATA_ACTIVE_TILE and requestListeningState(), and getting rid of your Binder and onBind() method.
I don't think you need all the service connection. I would add the meta data META_DATA_ACTIVE_TILE to the tile service manifest declaration, and then you can call TileService.requestListeningState(context, new ComponentName(context, TileService.class)); which will trigger onStartListening().
After that onStartListening() could call a method to update the Tile state/label/icon.
Also in your Tile service method to update the tile
I would add a check if (getQsTile !=null)
I have in my app preference activity with EditTextPreference and I added this, to detect, when the text in edittext is changed. All works, except for that, the code runs always twice... I tryed to add System.out.println("now"); to proove if the code runs twice, and it writes "now" two times...
Here is the code:
SharedPreferences.OnSharedPreferenceChangeListener myPrefListner;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.admin_activity);
myPrefListner = new SharedPreferences.OnSharedPreferenceChangeListener(){
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
switch(key) {
case "prefAddUser":
EditTextPreference connectionPref = (EditTextPreference) findPreference(key);
String jmeno = connectionPref.getText();
System.out.println("now");
add_user(jmeno); //custom method to add user to MySQL database
Toast.makeText(getApplicationContext(), "add user", Toast.LENGTH_SHORT).show();
connectionPref.setText("");
break;
}
}
};
}
#Override
protected void onResume() {
super.onResume();
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(myPrefListner);
}
#Override
protected void onPause() {
super.onPause();
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(myPrefListner);
}
I don't know what to do with this weird problem...
What should I do?
Calling OnSharedPreferenceChangeListener in anonymous class makes it become the target of garbage collection.
As soon as you leave the current scope and can cause unregisterOnSharedPreferenceChangeListener() to be call on a null context.
Implement it in the class scope like this:
public class SettingsActivity extends PreferenceActivity
implements OnSharedPreferenceChangeListener {
public static final String KEY_PREF_SYNC_CONN = "pref_syncConnectionType";
...
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
if (key.equals(KEY_PREF_SYNC_CONN)) {
Preference connectionPref = findPreference(key);
// Set summary to be the user-description for the selected value
connectionPref.setSummary(sharedPreferences.getString(key, ""));
}
}
}
Read the next tutorials for further explanation:
1. Good So answer on the subject
2. Official documentation here
I use Startapp as my ad network in my applications and I need to be able to handle when a user clicks on an ad. I could not find any documentation for this function, and I would rather use onPause() because other things might pause the activity. Help would be appreciated!
Try this:
YourStartAppAd.showAd(new AdDisplayListener() {
#Override
public void adHidden(Ad ad) {
}
#Override
public void adDisplayed(Ad ad) {
}
#Override
public void adClicked(Ad ad) {
}
});
https://github.com/StartApp-SDK/Documentation/wiki/android-advanced-usage
I'm rather new with Android, and with Java, for that matter, I apologize if the answer to my problem is a simple one.
The problem is that, once a certain Menu Item is selected, i need to run a rather long (2-3 seconds) task (involving HTTP requests, and as far as I know I need to execute said operation on a different thread than the main one) and then display part of the results gotten from the AsyncTask.
Everything works fine, except for the fact that the menu stays open the whole time the AsyncTask is being executed: I can't find a way of avoiding this.
I tried to sum up my problem with a shorter, but rather similar, example
Here's the MainActivity code:
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) {
super.onCreateOptionsMenu(menu);
menu.add(Menu.NONE,1,Menu.NONE,"Text");
return true;
}
#Override
public boolean onOptionsItemSelected (MenuItem mi) {
try {
String a = new AsyncTest ().execute().get();
Toast.makeText(MainActivity.this,a, Toast.LENGTH_SHORT).show();
return true;
}
catch (Exception e) {
return false;
}
}
}
And here's the AsyncTask
public class AsyncTest extends AsyncTask{
#Override
protected String doInBackground(Void... params) {
long i;
for (i=0;i<100000000;i++);
return "Lol";
}
}
I tried using closeOptionsMenu(); Right after onOptionsItemSelected, in order to close the Menu before the AsyncTask is executed, but it didn't work.
I didn't find much on the topic on google.
get() is blocking. so basically you are getting the work down on the other thread, but you are essentially waiting on the main UI thread preventing the menu from closing.
try this instead:
#Override
public boolean onOptionsItemSelected (MenuItem mi) {
new AsyncTest () {
public void onPostExecute(String result) {
Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT).show();
}
}.execute();
return true;
}