Cordova Plugin Stop/Restart Activity - java

I have a Cordova plugin which uses the https://github.com/googlesamples/android-Camera2Video example. I would like to disable the back button while in Camera.
To do this, I believe Fragments can't accept back button events, so have added an Activity to the plugin. I can successfully run the plugin, camera and activity, disabled the back button.
However when I close the plugin it errors with:
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
To get around this I have used commitAllowingStateLoss instead of commit however when I open the plugin the second time, it errors with:
java.lang.NullPointerException: Attempt to invoke interface method 'android.app.Activity org.apache.cordova.CordovaInterface.getActivity()' on a null object reference
I presume I'm not stopping the activity correctly, and allowing the state to be lost, which causes a second error. How do I get around this?
I've tried this method but no luck:
PhoneGap Android Plugin - close the plugin Activity
I've put my code in a branch here:
https://github.com/kmturley/cordova-plugin-media-custom/tree/feature/back-button
Add a summary of the changes:
plugin.xml
<config-file target="AndroidManifest.xml" parent="/manifest/application">
<activity android:name="com.example.android.camera2video.MediaCustomActivity" android:label="#string/activity_name" android:theme="#style/Theme.Transparent">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</config-file>
<source-file src="src/android/MediaCustom.java" target-dir="src/com/example/android/camera2video" />
<source-file src="src/android/MediaCustomActivity.java" target-dir="src/com/example/android/camera2video" />
<source-file src="src/android/Camera2VideoFragment.java" target-dir="src/com/example/android/camera2video" />
MediaCustom.java
public void show() {
if (cameraFragment != null) {
return;
}
cameraFragment = Camera2VideoFragment.newInstance(cordova, callbackContext);
cordova.getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
cordova.getActivity().setContentView(resources.getIdentifier("activity_camera", "layout", packageName));
FragmentManager fragmentManager = cordova.getActivity().getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(resources.getIdentifier("container", "id", packageName), cameraFragment);
fragmentTransaction.commit();
MediaCustomActivity.start(cordova.getActivity());
}
});
}
public void hide() {
if (cameraFragment == null) {
return;
}
cordova.getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
MediaCustomActivity.stop(cordova.getActivity());
cordova.getActivity().setContentView(getView());
FragmentManager fragmentManager = cordova.getActivity().getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.remove(cameraFragment);
fragmentTransaction.commitAllowingStateLoss(); // commit();
cameraFragment = null;
}
});
}
MediaCustomActivity.java
public static void start(Activity activity) {
Intent intent = new Intent(activity, MediaCustomActivity.class);
activity.startActivity(intent);
}
public static void stop(Activity activity) {
// what can we do here?
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.init();
Window window = this.getWindow();
window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
return false;
}
return super.onKeyDown(keyCode, event);
}

Related

Android SearchView.OnQueryTextListener() Unexpectedly Launching an Intent

I have implemented a Searchview into my application, and have run into a weird problem. Basically, the user is able to enter a string to be searched and it is submitted properly. However, my application will filter the ListView based on the search query, and then an Intent will be launched resulting in the activity starting again and returning to it's original state where it is displaying all the results.
Here is the related code.
#Override
public boolean onCreateOptionsMenu(Menu menu) {
...
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
updateEntriesView(dbHelper.queryByName(query));
Toast.makeText(getApplicationContext(), "Searching for " + query, Toast.LENGTH_LONG).show();
return true;
}
#Override
public boolean onQueryTextChange(String newText) {
return false;
}
});
}
private void updateEntriesView(ArrayList<Entry> response) {
mListView = (ListView) findViewById(R.id.listview_entries);
if (adapter == null) {
adapter = new EntryListAdapter(EntriesActivity.this, R.layout.row_entry_layout, response);
mListView.setAdapter(adapter);
} else {
adapter.clear();
adapter.addAll(response);
adapter.notifyDataSetChanged();
}
adapter.setNotifyOnChange(true);
}
I can not figure out to change this behavior and I can not find any documentation regarding it's implementation online. Is there a way I can override this feature and prevent it from launching an intent and restarting the activity to it's original unfiltered state?
EDIT:
I was able to solve this issue myself. For anyone who may be having the same problem here was my solution.
So I had an intent-filter in my AndroidManifest.xml under the activity that would launch an intent upon a search action. This is what was causing it to launch an intent and start a new instance of my activity.
My solution to this was to convert this activity into a single top activity and add code to handle the intent. By making the activity single top, it allows the activity to handle incoming intents without starting up a new instance of the intent. For a more detailed description on the difference between a normal and single top activity, this is a good article on the subject https://www.mobomo.com/2011/06/android-understanding-activity-launchmode/
Now, because my activity is single top, I can override the onNewIntent() method and add my code for handling this intent without having it launch a new instance. The relevant code for solving my problem is below.
AndroidManifest.xml
<activity android:name=".EntriesActivity"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
<meta-data
android:name="android.app.searchable"
android:resource="#xml/searchable"></meta-data>
</activity>
EntriesActivity.java
public class EntriesActivity extends AppCompatActivity {
...
#Override
public boolean onCreateOptionsMenu(Menu menu) {
...
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
updateEntriesView(dbHelper.queryByName(query));
Toast.makeText(getApplicationContext(), "Searching for " + query, Toast.LENGTH_LONG).show();
return true;
}
#Override
public boolean onQueryTextChange(String newText) {
return false;
}
});
}
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
handleIntent(intent);
}
private void handleIntent(Intent intent) {
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
String query = intent.getStringExtra(SearchManager.QUERY);
updateEntriesView(dbHelper.queryEntriesByName(query));
}
}
private void updateEntriesView(ArrayList<Entry> response) {
if (adapter == null) {
adapter = new EntryListAdapter(EntriesActivity.this, R.layout.row_entry_layout, response);
mEntriesList.setAdapter(adapter);
} else {
adapter.clear();
adapter.addAll(response);
adapter.notifyDataSetChanged();
}
adapter.setNotifyOnChange(true);
}
}
I hope this helps.
You need to clear focus of the text view using searchView.clearFocus();
Refer This Answer: https://stackoverflow.com/a/15127252/7710739
I know this is old but if your searching and resulting in the same Activity try removing the
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
It should not try to launch a new activity then i don't beleive.

Android UnityPlayerActivity Action Bar

I am building an Android application which includes a Unity 3d interactive experience.
I have imported the Unity project into Android Studio but when launched the activity is fullscreen and does not show the Android action bar.
How can I do this?
Integration Steps
Create new Unity project.
Export "Google Android Project" from Unity.
Import project into Android Studio.
Attempted Solutions
Changing the theme in the manifest.
Setting the theme in the UnityPlayerActivity Java class.
Overriding the Unity Android Manifest by placing a manifest with an updated theme in the Unity directory /Assets/Plugins/Android.
Changing UnityPlayerActivity to extend AppCompatActivity. This will show the action bar but there is a white gap between it and the status bar.
Setting "Screen.fullScreen = false;" in Unity SceneManager. This removes the immersive mode so that the Android status bar is visible.
Turning off "Status Bar Hidden" in player settings. Appears to have no effect.
Wrapping the UnityPlayer in a FrameLayout. This allows me to resize the the Unity as a view.
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.company.unity.test"
android:installLocation="preferExternal"
android:versionCode="1"
android:versionName="1.0">
<supports-screens
android:anyDensity="true"
android:largeScreens="true"
android:normalScreens="true"
android:smallScreens="true"
android:xlargeScreens="true" />
<application
android:banner="#drawable/app_banner"
android:debuggable="false"
android:icon="#drawable/app_icon"
android:isGame="true"
android:label="#string/app_name"
android:theme="#android:style/Theme.NoTitleBar.Fullscreen">
<activity
android:name="com.company.unity.test.UnityPlayerActivity"
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale"
android:label="#string/app_name"
android:launchMode="singleTask"
android:screenOrientation="fullSensor">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
</intent-filter>
<meta-data
android:name="unityplayer.UnityActivity"
android:value="true" />
</activity>
</application>
<uses-sdk
android:minSdkVersion="9"
android:targetSdkVersion="23" />
<uses-feature android:glEsVersion="0x00020000" />
<uses-feature
android:name="android.hardware.sensor.accelerometer"
android:required="false" />
<uses-feature
android:name="android.hardware.touchscreen"
android:required="false" />
<uses-feature
android:name="android.hardware.touchscreen.multitouch"
android:required="false" />
<uses-feature
android:name="android.hardware.touchscreen.multitouch.distinct"
android:required="false" />
</manifest>
UnityPlayerActivity.java
package com.company.unity.test;
import android.app.Activity;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.Window;
import com.unity3d.player.UnityPlayer;
public class UnityPlayerActivity extends Activity
{
protected UnityPlayer mUnityPlayer; // don't change the name of this variable; referenced from native code
// Setup activity layout
#Override protected void onCreate (Bundle savedInstanceState)
{
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
getWindow().setFormat(PixelFormat.RGBX_8888); // <--- This makes xperia play happy
mUnityPlayer = new UnityPlayer(this);
setContentView(mUnityPlayer);
mUnityPlayer.requestFocus();
}
// Quit Unity
#Override protected void onDestroy ()
{
mUnityPlayer.quit();
super.onDestroy();
}
// Pause Unity
#Override protected void onPause()
{
super.onPause();
mUnityPlayer.pause();
}
// Resume Unity
#Override protected void onResume()
{
super.onResume();
mUnityPlayer.resume();
}
// This ensures the layout will be correct.
#Override public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
mUnityPlayer.configurationChanged(newConfig);
}
// Notify Unity of the focus change.
#Override public void onWindowFocusChanged(boolean hasFocus)
{
super.onWindowFocusChanged(hasFocus);
mUnityPlayer.windowFocusChanged(hasFocus);
}
// For some reason the multiple keyevent type is not supported by the ndk.
// Force event injection by overriding dispatchKeyEvent().
#Override public boolean dispatchKeyEvent(KeyEvent event)
{
if (event.getAction() == KeyEvent.ACTION_MULTIPLE)
return mUnityPlayer.injectEvent(event);
return super.dispatchKeyEvent(event);
}
// Pass any events not handled by (unfocused) views straight to UnityPlayer
#Override public boolean onKeyUp(int keyCode, KeyEvent event) { return mUnityPlayer.injectEvent(event); }
#Override public boolean onKeyDown(int keyCode, KeyEvent event) { return mUnityPlayer.injectEvent(event); }
#Override public boolean onTouchEvent(MotionEvent event) { return mUnityPlayer.injectEvent(event); }
/*API12*/ public boolean onGenericMotionEvent(MotionEvent event) { return mUnityPlayer.injectEvent(event); }
}
for Unity version 5.5 best way to avoid Immersive Mode in Android is to pass in the constructor not an Activity but to cast of the ApplicationContext to the Wrapper Context.
mUnityPlayer = new UnityPlayer((ContextWrapper) getApplicationContext());
That works because in the obfuscated UnityPlayer.class (in unity-classes.jar) there is a check of instance.
private void h() {
if(this.h instanceof Activity) {
((Activity)this.h).getWindow().setFlags(1024, 1024);
}
}
So if it's not an Activity the UnityPlayer.class doesn't set the flag.
I think I've found solution.
Change that line:
mUnityPlayer = new UnityPlayer(this);
so it creates your own UnityPlayer subclass, which overrides setFullscreen method (little bit hacky):
public class UnityPlayerWrapper extends UnityPlayer {
public UnityPlayerWrapper(ContextWrapper contextWrapper) {
super(contextWrapper);
}
#Override
protected void setFullscreen(boolean b) {
super.setFullscreen(false);
}
}
In addition, please remove that line: requestWindowFeature(Window.FEATURE_NO_TITLE);
Piotr answer is working for older version and Lorenzo DM's answer also valid but
mUnityPlayer = new UnityPlayer((ContextWrapper) getApplicationContext());
not working in some devices. So Finally I've modify UnityPlayerActivity here is new solution
public class UnityPlayerActivity extends AppCompatActivity
{
protected UnityPlayer mUnityPlayer; // don't change the name of this variable; referenced from native code
ActionBar actionBar;
private Toolbar toolbar;
private FrameLayout unityContainer;
// Setup activity layout
#Override protected void onCreate (Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
mUnityPlayer = new UnityPlayer(this);
setContentView(R.layout.activity_unity_player);
mappingWidgets();
init();
}
void mappingWidgets(){
toolbar = (Toolbar) findViewById(R.id.toolbar);
unityContainer = (FrameLayout) findViewById(R.id.unity_container);
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);
unityContainer.addView(mUnityPlayer.getView(), 0, layoutParams);
mUnityPlayer.requestFocus();
}
void init(){
setSupportActionBar(toolbar);
actionBar = getSupportActionBar();
if (actionBar != null)
actionBar.setDisplayHomeAsUpEnabled(true);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
finish();
onDestroy();
}
});
setTitle(getString(R.string.app_name));
}
#Override protected void onNewIntent(Intent intent)
{
setIntent(intent);
}
// Quit Unity
#Override protected void onDestroy ()
{
mUnityPlayer.quit();
super.onDestroy();
}
// Pause Unity
#Override protected void onPause()
{
super.onPause();
mUnityPlayer.pause();
}
// Resume Unity
#Override protected void onResume()
{
super.onResume();
mUnityPlayer.resume();
}
// Low Memory Unity
#Override public void onLowMemory()
{
super.onLowMemory();
mUnityPlayer.lowMemory();
}
// Trim Memory Unity
#Override public void onTrimMemory(int level)
{
super.onTrimMemory(level);
if (level == TRIM_MEMORY_RUNNING_CRITICAL)
{
mUnityPlayer.lowMemory();
}
}
// This ensures the layout will be correct.
#Override public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
mUnityPlayer.configurationChanged(newConfig);
}
// Notify Unity of the focus change.
#Override public void onWindowFocusChanged(boolean hasFocus)
{
super.onWindowFocusChanged(hasFocus);
mUnityPlayer.windowFocusChanged(hasFocus);
}
// For some reason the multiple keyevent type is not supported by the ndk.
// Force event injection by overriding dispatchKeyEvent().
#Override public boolean dispatchKeyEvent(KeyEvent event)
{
if (event.getAction() == KeyEvent.ACTION_MULTIPLE)
return mUnityPlayer.injectEvent(event);
return super.dispatchKeyEvent(event);
}
// Pass any events not handled by (unfocused) views straight to UnityPlayer
//#Override public boolean onKeyUp(int keyCode, KeyEvent event) { return mUnityPlayer.injectEvent(event); }
// Pass any events not handled by (unfocused) views straight to UnityPlayer
#Override public boolean onKeyUp(int keyCode, KeyEvent event) {
if(keyCode == KeyEvent.KEYCODE_BACK) {
finish();
onDestroy();
return true;
}
return mUnityPlayer.injectEvent(event); }
#Override public boolean onKeyDown(int keyCode, KeyEvent event) { return mUnityPlayer.injectEvent(event); }
#Override public boolean onTouchEvent(MotionEvent event) { return mUnityPlayer.injectEvent(event); }
/*API12*/ public boolean onGenericMotionEvent(MotionEvent event) { return mUnityPlayer.injectEvent(event); }
}

Showing activity from onCreate

Problem Description
I have two activities in my application MainActivity and BannerActivity. From the main activity I start BannerActivity in onCreate method. But I first I see MainActivity screen for a second and then BannerActivity screen.
Question
How I can do so that BannerActivity will be shown first and after countdown timer will stop and BannerActivity will close after that MainActivity come to the screen.
MainActivity
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/* Show banner activity for several seconds then close it. */
Intent bannerIntent = new Intent(MainActivity.this, BannerActivity.class);
this.startActivity(bannerIntent);
}
};
BannerActivity
public class BannerActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
/* Make banner fullscreen. */
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_banner);
/* Launch count down timer for several seconds. */
CountDownTimer countDownTimer = new CountDownTimer(3000, 1000) {
#Override
public void onTick(long millisUntilFinished) { /* Not used. */ }
#Override
public void onFinish() {
BannerActivity.this.finish();
}
}.start();
}
#Override
public void onBackPressed() {
/* Lock back button presses. */
super.onBackPressed();
}
};
You need a SplashScreen:
http://www.thiagorosa.com.br/en/tutorial/part01-splash-screen
public class GameSplash extends Activity {
// time to wait on the splash screen
private static final int SPLASH_SCREEN_DELAY = 3000;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
new Thread() {
#Override
public void run() {
try {
// do any heavy initialization here
// wait a few seconds before going to the next screen
sleep(SPLASH_SCREEN_DELAY);
}
catch (InterruptedException e) {
}
catch (Exception e) {
}
finally {
// start the level selection screen
Intent intentSelect = new Intent(GameSplash.this, GameSelect.class);
startActivity(intentSelect);
}
}
}.start();
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// ignore any key press on the splash screen
return true;
}
}
Run first BannerActivity and in the contdown run MainActivity rather than BannerActivity.this.finish();
You can start with BannerActivity and then when the time expires you go to MainActivity and clear the history stack by using this intent flag (so that you can't go back to the BannerActivity using the back button).
Intent.FLAG_ACTIVITY_CLEAR_TASK
Swap the activites on the Manifest to decide which activity is run first :
<activity
android:name="com.yourpackagename.MainActivity"
android:label="#string/app_name" >
</activity>
<activity
android:name="com.yourpackagename.BannerActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
The BannerActivity should have the <intent-filter> tag and set as Main and Launcher as the example. This will make Banner activity as the Initial Activity when you start your application.
After that you can just implement countdowntimer and start MainActivity when the timer ends.
Hope this helps, Good Luck ^^
try to use this way first need to load xml layout
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_banner);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
or try to put in manifest like
<activity
android:name=".BannerActivity"
android:label="#string/app_name"
android:theme="#android:style/Theme.NoTitleBar.Fullscreen"
>
you can do like this also in your Banner Activity
use this code in oncreate method in banner activity
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
finish();
}
}, 2000);
You need splash screen. Try this:
Start BanerActivity first. And make its onCreate like
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Thread welcomeThread = new Thread() {
int wait = 0;
#Override
public void run() {
try {
super.run();
while (wait < 5000) { //Wait of 5 seconds
sleep(500);
wait += 500;
}
} catch (Exception e) {
} finally {
Intent i = new Intent(BanerActivity.this,
MainActivity.class);
startActivity(i);
finish();
}
}
};
welcomeThread.start();
}
Hope this helps.
the easiest solution is to make the BannerActivity the launcher activity and modify the CountDownTimer to be
#Override
public void onFinish()
{
Intent mainIntent = new Intent(this, MainActivity.class);
startActivity(mainIntent);
finish();
}
then adjust the manifest file to make the BannerActivity as the launcher activity and remove it from the MainActivity

Check if app is open during a GCM onMessage event?

I am wondering how to check if my application is open and currently visible to the user when receiving an onMessage() from GCM. At first, I was just using my own boolean isVisible, but then I realized this isn't reliable, because if the app isn't open, the object I use to access that flag is null. While this in itself could be used to see if the app is open, it seems a little bit messy. Is there a way in Android from a system level to somehow check if the application is currently open, and if the user is viewing the app? Keep in mind an app could technically be running, but not be visible, because a user has recently pressed the "home" button sending it to the background.
#Override
protected void onMessage(Context arg0, Intent arg1) {
String turn = intent.getExtras().getString("turn");
if (turn.equals("yours"){
if (/*app is open*/){ <------------------ what can go here?
// dont generate a notification
// display something in the game instead
}
else{
// generate notification telling player its their turn
}
}
}
I would use order broadcasts to do that.
In your onMessage method:
Intent responseIntent = new Intent("com.yourpackage.GOT_PUSH");
sendOrderedBroadcast(responseIntent, null);
In your Activity:
public class YourActivity extends Activity {
final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//Right here do what you want in your activity
abortBroadcast();
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//.....
}
#Override
protected void onPause() {
unregisterReceiver(mBroadcastReceiver);
super.onPause();
}
#Override
protected void onResume() {
IntentFilter filter = new IntentFilter("com.yourpackage.GOT_PUSH");
filter.setPriority(2);
registerReceiver(mBroadcastReceiver, filter);
super.onResume();
}
}
The other BroadcastReceiver
public class SecondReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
//In this receiver just send your notification
}
}
Manifest:
<activity
android:name=".YourActivity"
android:label="#string/app_name">
<intent-filter>
<action
android:name="android.intent.action.MAIN" />
<category
android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".SecondReceiver">
<intent-filter
android:priority="1">
<action
android:name="com.yourpackage.GOT_PUSH" />
</intent-filter>
</receiver>
Basically in the onMessage method you send an Intent which is first received by the BroadcastReceiver registered inside YourActivity if it is running and in foreground, otherwise it is received by the SecondReceiver.
Use SharedPreferences saving the boolean isVisible, and when you get the value from the preference you can add a default value.
SharedPreferences settings = context.getSharedPreferences("NAME_XXX", Activity.MODE_PRIVATE);
settings.getBoolean("visible", false);
What I always do is have a reference to the current Activity.
I set the current Activity in every onResume to this and set it to null in every onPause.
If the current Activity is null then the app is not open. If it's not null you can see if the correct Activity is open and deliver it to that Activity.
GCMIntentService:
public static Activity currentActivity;
public static final Object CURRENTACTIVIYLOCK = new Object();
#Override
protected void onHandleIntent(Intent intent) {
synchronized(CURRENTACTIVIYLOCK) {
if (currentActivity != null) {
if (currentActivity.getClass() == CorrectActivity.class) {
CorrectActivity act = (CorrectActivity)currentActivity;
act.runOnUiThread(new Runnable() {
public void run() {
// Notifiy activity
}
});
} else {
// show notification ?
}
} else {
// show notification
}
}
}
CorrectActivity:
#Override
protected void onResume() {
synchronized (GCMIntentService.CURRENTACTIVITYLOCK) {
GCMIntentService.currentActivity = this;
}
}
super.onResume();
}
#Override
protected void onPause() {
synchronized (GCMIntentService.CURRENTACTIVITYLOCK) {
GCMIntentService.currentActivity = null;
}
super.onPause();
}
The thing that worked for me:
Create a final Class Constants, inside it, create static varaiable:
public final class Constants{
public static AppCompatActivity mCurrentActivity;
}
Now, on each on resume of your activties say:
#Override
protected void onResume() {
super.onResume();
Constants.mCurrentActivity = this;
}
When receieving notification, check if current activity is null, if its null, application is not opened, if activity isn't null, you can check things like:
if(Constants.mCurrentActivity instanceof MainActivity){
((MainActivity) Constants.mCurrentActivity).yourPublicMethodOrStaticObject;
}

Android: onTouchEvent start new activity

I have been searching for a while now but can't find a working solution for my android code. Well at least one I am able to implement.
I have an activity (StartActivity) with a few animations. Then I have an onTouchEvent. This works fine to prompt a few more animations however after this I want to open a new Activity.
Here is my code:
public class StartActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.start);
RunAnimations(R.anim.translate1, R.anim.translate2);
}
public void RunAnimations(int t1, int t2) {
Animation a = AnimationUtils.loadAnimation(this, t1);
a.reset();
Animation b = AnimationUtils.loadAnimation(this, t2);
b.reset();
ImageView drop = (ImageView) findViewById(R.id.drop);
ImageView iflush = (ImageView) findViewById(R.id.iflush);
drop.clearAnimation();
iflush.clearAnimation();
drop.startAnimation(a);
iflush.startAnimation(b);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
RunAnimations(R.anim.translate3, R.anim.translate4);
}
return true;
}
}
In the onTouchEvent, after calling RunAnimations, I want to start a new activity (TipActivity). That is all.
Add another activity to you AndroidManifest file like so:
<activity
android:label="YourActivity"
android:name=".YourActivity" >
<intent-filter >
<action android:name="net.learn2develop.YourActivity" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
And then you could do something like (after calling RunAnimations()) :
startActivity(new Intent("net.learn2develop.YourActivity"));
Hope that helps.
Use that:
Intent intent=new Intent(context, TipActivity.class);
startActivity(intent);
overridePendingTransition(R.anim.translate3, R.anim.translate4);
^-^

Categories