Admob locks call screen android - android

I am trying to show Advertisement on phone call screen. But something is wrong. I am trying to show just 1 view that child of window manager. It shows the Advertisement well but i can't decline or accept the phone. I also try non-Task and Thread or else. Please help me to solve this. Thanks :)
public class StateListener extends PhoneStateListener {
AdvertisementService advertisementService = new AdvertisementService();
private static int lastState = TelephonyManager.CALL_STATE_IDLE;
private Intent intent;
private static AdView mView =null;
private WindowManager manager;
private static final String AdID = "<TEST_DEVICE_ID>";
private AdRequest adRequest = new AdRequest.Builder().addTestDevice(AdID).build();
Context context;
public StateListener(Context context) {
this.context = context;
LoadAdvertisementTask task = new LoadAdvertisementTask();
task.execute();
}
private class LoadAdvertisementTask extends AsyncTask<Void,Void,Void>{
private WindowManager.LayoutParams params;
#Override
protected void onPreExecute() {
if(mView==null){
mView = new AdView(context);
mView.setAdUnitId(context.getResources().getString(R.string.banner_ad_unit_id));
mView.setAdSize(AdSize.BANNER);
}
mView.loadAd(adRequest);
manager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_PHONE,
WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.TOP | Gravity.LEFT;
params.x = 0;
Display display = manager.getDefaultDisplay();
Point pnt = new Point();
display.getSize(pnt);
params.y = pnt.y/2;
}
#Override
protected Void doInBackground(Void... voids) {
try{
}catch(Exception ex){
ex.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
mView.setVisibility(View.INVISIBLE);
manager.addView(mView, params);
}
}
#Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state){
case TelephonyManager.CALL_STATE_IDLE:
Toast.makeText(context,"IDLE",Toast.LENGTH_SHORT).show();
if(mView!=null)
mView.setVisibility(View.INVISIBLE);
// manager.removeView(mView);
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Toast.makeText(context,"OFFHOOK",Toast.LENGTH_SHORT).show();
if(mView!=null)
mView.setVisibility(View.INVISIBLE);
break;
case TelephonyManager.CALL_STATE_RINGING:
if(mView!=null)
mView.setVisibility(View.INVISIBLE);
//telefon caliyo
Toast.makeText(context,"RINGRING",Toast.LENGTH_SHORT).show();
break;
default:
break;
}
}
}

Related

How to show interstitial ad with multiple screens in libgdx?

I successfully implemented banner ad in my libgdx game, now i am trying to implementing interstitial ad. I want to show ad on the button click but the ad is not showing on the screen, i am using log to know if the ad is loading and it is loading everytime but not visible on the screen. i am using multiple screen classes in the game. I have watched several tutorials on it but nothing seems to work.
public class AndroidLauncher extends AndroidApplication implements AdService{
private InterstitialAd interstitialAd;
private ScheduledExecutorService scheduler;
private static final String BANNER_ID = "ca-app-pub-3940256099942544/6300978111";
#Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
//create a gameView and a bannerAd AdView
RelativeLayout layout = new RelativeLayout(this);
// Do the stuff that initialize() would do for you
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
// Create the libgdx View
View gameView = initializeForView(new BabyGame(this), config);
// Create and setup the AdMob view
AdView adView = new AdView(this);
adView.setAdSize(AdSize.BANNER);
adView.setAdUnitId(BANNER_ID); // Put in your secret key here
AdRequest adRequest = new AdRequest.Builder().addTestDevice("6D0D171A0065AD4E19656B813BC8F493").build();
adView.loadAd(adRequest);
// Add the libgdx view
layout.addView(gameView);
// Add the AdMob view
RelativeLayout.LayoutParams adParams =
new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
adParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
adParams.addRule(RelativeLayout.CENTER_IN_PARENT);
layout.addView(adView, adParams);
// Hook it all up
setContentView(layout);
interstitialAd = new InterstitialAd(this);
interstitialAd.setAdUnitId("ca-app-pub-3940256099942544/1033173712");
interstitialAd.setAdListener(new AdListener() {
#Override
public void onAdLoaded() {}
#Override
public void onAdClosed() {
loadIntersitialAd();
}
});
loadIntersitialAd();
}
private void loadIntersitialAd(){
AdRequest interstitialRequest = new AdRequest.Builder().build();
interstitialAd.loadAd(interstitialRequest);
}
#Override
public void showInterstitial() {
runOnUiThread(new Runnable() {
public void run() {
if (interstitialAd.isLoaded())
interstitialAd.show();
else
loadIntersitialAd();
}
});
}
#Override
public boolean isInterstitialLoaded() {
return interstitialAd.isLoaded();
}
}
This is the BabyGame.java
public class BabyGame extends Game
{
public AdService adService;
BabyGame(AdService ads){
adService = ads;
}
public void create()
{
BabyOrange bp = new BabyOrange(this);
setScreen( bp );
}
}
here is the interface
public interface AdService {
boolean isInterstitialLoaded();
void showInterstitial();
}
I want to show ads here in the BabyOrange.java when the button touched.
public class BabyOrange extends BabyScreen {
private BabyActor bg;
private BabyActor phone;
private ImageButton buttonLeft,buttonRight;
public AdService adService;
private Table table;
private AssetManager asset;
private TextureAtlas atlas;
public BabyOrange(Game g){
super(g);
}
#Override
public void create() {
asset = new AssetManager();
asset.load("background-orange.png",Texture.class);
asset.load("orange-ph.png",Texture.class);
asset.finishLoading();
bg = new BabyActor();
bg.setTexture(asset.get("background-orange.png",Texture.class));
bg.setSize(Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
ph = new BabyActor();
ph.setTexture(asset.get("orange-ph.png",Texture.class));
ph.setSize(Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
TextureRegion btLeft = new TextureRegion(new Texture("NUMBEROFF.png"));
Drawable drawableLeft = new TextureRegionDrawable(new TextureRegion(btLeft));
buttonLeft = new ImageButton(drawableLeft);
TextureRegion btRight = new TextureRegion(new Texture("VEHICLEOFF.png"));
Drawable drawableRight = new TextureRegionDrawable(new TextureRegion(btRight));
buttonRight = new ImageButton(drawableRight);
stage.addActor(bg);
stage.addActor(phone);
Gdx.input.setInputProcessor(stage);
buttonRight.addListener(new InputListener(){
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
game.setScreen(new BabyGreen(game));
RunnableAction playWooshAction = Actions.run(new Runnable() {
#Override
public void run() {
adService.showInterstitial();
}
});
return true;
}
});
buttonLeft.addListener(new InputListener(){
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
game.setScreen(new BabyBlue(game));
return true;
}
});
table = new Table();
table.padLeft(40);
table.setPosition(phone.getWidth()/2,phone.getHeight()/2*0.6f);
table.row().size(stage1.getWidth()/100*20,stage1.getWidth()/100*20);
table.add(buttonLeft);
table.add(buttonCenter);
table.add(buttonRight);
stage.addActor(table);
}
public void dispose(){
bg.getRegion().getTexture().dispose();
phone.getRegion().getTexture().dispose();
stage.dispose();
stage1.dispose();
}
}

UI not populating ListView with items saved in SQLite Database

I've been facing issues with my MoviesApp for a while now and I feel that I've exhausted all my knowledge on this; I am quite new with Android so bear with me :-)
MoviesApp is a simple movie listing app, in which the user can scroll through the list of films, see details for each one and save their favorites in an SQLite DB.
I use SharedPreference to sort movies based by popularity, rating and favorites (the only list saved in the database), but when I change through each one, the UI is not updating at all.
I am really stuck and honestly, I could do with another pair of eyes, because, even if the answer is staring me in the face, I wouldn't be able to see it 😫😫😫
I pasted the link to the project below:
https://drive.google.com/file/d/1SweLpwfo5RntXrbtLPP3N_xS1bVs32Ze/view?usp=sharing
Thank you!!
Update: I believe the problem would in the MainActivity class, where the RecyclerView Loader is declared - specifically in onLoadFinished().
#SuppressWarnings({"WeakerAccess", "unused", "CanBeFinal"})
public class MainActivity extends AppCompatActivity implements
LoaderManager.LoaderCallbacks,
MovieAdapter.MovieDetailClickHandler, SwipeRefreshLayout.OnRefreshListener {
private static final String TAG = MainActivity.class.getSimpleName();
public static final String MOVIE_ID = "movieId";
private final static String LIFECYCLE_CALLBACKS_LAYOUT_MANAGER_KEY = "KeyForLayoutManagerState";
Parcelable savedLayoutManagerState;
public RecyclerView movieListRV;
private GridLayoutManager gridLayoutManager =
new GridLayoutManager(this, 1);
Context context = this;
// Loader IDs for loading the main API and the poster API, respectively
private static final int ID_LOADER_LIST_MOVIES = 1;
private static final int ID_LOADER_CURSOR = 2;
// adapter
private MovieAdapter adapter;
// detect internet connection
NetworkDetection networkDetection;
// swipe to refresh
SwipeRefreshLayout swipeRefreshLayout;
// sortOption
String sortOption = null;
// movie projection
private final String[] projection = new String[]{
MoviesContract.MovieEntry.COLUMN_MOVIE_POSTER,
MoviesContract.MovieEntry.COLUMN_MOVIE_ID
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Stetho.initializeWithDefaults(this);
Toolbar toolbar = findViewById(R.id.settings_activity_toolbar);
setSupportActionBar(toolbar);
toolbar.setTitleTextColor(Color.WHITE);
networkDetection = new NetworkDetection(this);
swipeRefreshLayout = findViewById(R.id.discover_swipe_refresh);
swipeRefreshLayout.setOnRefreshListener(MainActivity.this);
swipeRefreshLayout.setColorScheme(android.R.color.holo_red_dark);
movieListRV = findViewById(R.id.recycler_view_movies);
movieListRV.setLayoutManager(gridLayoutManager);
movieListRV.setHasFixedSize(true);
ViewTreeObserver viewTreeObserver = movieListRV.getViewTreeObserver();
viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
calculateSize();
}
});
adapter = new MovieAdapter(this, this);
movieListRV.setAdapter(adapter);
RecyclerViewItemDecorator itemDecorator = new RecyclerViewItemDecorator(context,
R.dimen.item_offset);
movieListRV.addItemDecoration(itemDecorator);
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences
(context);
SharedPreferences.OnSharedPreferenceChangeListener preferenceChangeListener = new
SharedPreferences.OnSharedPreferenceChangeListener() {
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
adapter.deleteItemsInList();
onRefresh();
if (key.equals(getString(R.string.pref_sort_by_key))) {
initializeloader();
}
}
};
preferences.registerOnSharedPreferenceChangeListener(preferenceChangeListener);
initializeloader();
}
private static final int sColumnWidth = 200;
private void calculateSize() {
int spanCount = (int) Math.floor(movieListRV.getWidth() / convertDPToPixels(sColumnWidth));
((GridLayoutManager) movieListRV.getLayoutManager()).setSpanCount(spanCount);
}
#SuppressWarnings("SameParameterValue")
private float convertDPToPixels(int dp) {
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
float logicalDensity = metrics.density;
return dp * logicalDensity;
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable(LIFECYCLE_CALLBACKS_LAYOUT_MANAGER_KEY, gridLayoutManager
.onSaveInstanceState());
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
if (savedInstanceState != null) {
savedLayoutManagerState = savedInstanceState.getParcelable
(LIFECYCLE_CALLBACKS_LAYOUT_MANAGER_KEY);
movieListRV.getLayoutManager().onRestoreInstanceState(savedLayoutManagerState);
}
}
#Override
public Loader onCreateLoader(int id, Bundle args) {
adapter.deleteItemsInList();
String urlMovieActivity;
switch (id) {
case ID_LOADER_CURSOR:
return new CursorLoader(context, MoviesContract.MovieEntry.MOVIES_CONTENT_URI,
projection, null, null, null);
case ID_LOADER_LIST_MOVIES:
urlMovieActivity = NetworkUtils.buildUrlMovieActivity(context, sortOption);
return new MovieLoader(this, urlMovieActivity);
default:
return null;
}
}
#Override
public void onLoadFinished(Loader loader, Object data) {
adapter.deleteItemsInList();
TextView noMoviesMessage = findViewById(R.id.no_movies_found_tv);
switch (loader.getId()) {
case ID_LOADER_CURSOR:
adapter.InsertList(data);
break;
case ID_LOADER_LIST_MOVIES:
//noinspection unchecked
List<MovieItem> movieItems = (List<MovieItem>) data;
if (networkDetection.isConnected()) {
noMoviesMessage.setVisibility(View.GONE);
adapter.InsertList(movieItems);
movieListRV.getLayoutManager().onRestoreInstanceState(savedLayoutManagerState);
} else {
noMoviesMessage.setVisibility(View.VISIBLE);
}
break;
}
adapter.notifyDataSetChanged();
}
#Override
public void onLoaderReset(Loader loader) {
switch (loader.getId()) {
case ID_LOADER_CURSOR:
adapter.InsertList(null);
break;
case ID_LOADER_LIST_MOVIES:
adapter.InsertList(null);
break;
}
}
#Override
public void onPostResume(Loader loader) {
super.onPostResume();
getLoaderManager().initLoader(ID_LOADER_CURSOR, null, this);
}
#Override
public void onSelectedItem(int movieId) {
Intent goToDetailActivity = new Intent(this, DetailMovieActivity.class);
goToDetailActivity.putExtra(MOVIE_ID, movieId);
startActivity(goToDetailActivity);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_general, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem menuItem) {
int id = menuItem.getItemId();
if (id == R.id.action_general_settings) {
Intent goToSetting = new Intent(this, SettingsActivity.class);
startActivity(goToSetting);
return true;
} else if (id == R.id.action_refresh) {
onRefresh();
}
return super.onOptionsItemSelected(menuItem);
}
/**
* Called when a swipe gesture triggers a refresh.
*/
#Override
public void onRefresh() {
adapter.deleteItemsInList();
swipeRefreshLayout.setRefreshing(false);
restartloader();
adapter.notifyDataSetChanged();
}
private void restartloader() {
adapter.deleteItemsInList();
if (MoviePreferences.getSortByPreference(context).equals(getString(R.string
.pref_sort_by_favourite))) {
getLoaderManager().restartLoader(ID_LOADER_CURSOR, null, MainActivity
.this);
}
if (MoviePreferences.getSortByPreference(context).equals(getString(R.string
.pref_sort_by_popularity))) {
sortOption = NetworkUtils.MOST_POPULAR_PARAM;
getLoaderManager().restartLoader(ID_LOADER_LIST_MOVIES, null,
MainActivity.this);
}
if (MoviePreferences.getSortByPreference(context).equals(getString(R.string
.pref_sort_by_rating))) {
sortOption = NetworkUtils.TOP_RATED_PARAM;
getLoaderManager().restartLoader(ID_LOADER_LIST_MOVIES, null,
MainActivity.this);
}
adapter.notifyDataSetChanged();
}
public void initializeloader() {
restartloader();
if (MoviePreferences.getSortByPreference(context).equals(getString(R.string
.pref_sort_by_favourite))) {
getLoaderManager().initLoader(ID_LOADER_CURSOR, null, MainActivity
.this);
}
if (MoviePreferences.getSortByPreference(context).equals(getString(R.string
.pref_sort_by_popularity))) {
onRefresh();
sortOption = NetworkUtils.MOST_POPULAR_PARAM;
getLoaderManager().initLoader(ID_LOADER_LIST_MOVIES, null,
MainActivity.this);
}
if (MoviePreferences.getSortByPreference(context).equals(getString(R.string
.pref_sort_by_rating))) {
onRefresh();
sortOption = NetworkUtils.TOP_RATED_PARAM;
getLoaderManager().initLoader(ID_LOADER_LIST_MOVIES, null,
MainActivity.this);
}
adapter.notifyDataSetChanged();
}
}

How to find memory leaks using LeakCanary in the Android app?

Help please find memory leaks in my app.
LeakCanary:
-static android.app.ActivityThread.sCurrentActivityThread
-references android.utill.ArrayMap.mArray
-reference array java.lang.Object[].1
-references android.app.ActivityThread$ActivityClientRecord.activity
-references MainActivity.tf (tf - my fragment)
-leaks TheaterFragment instance
Example code fragment:
public class TheaterFragment extends Fragment {
Typeface face;
private View view;
private RelativeLayout rl;
private LinearLayout linearLayout;
private int wordLheigh, screenWidht, wordLength, margin, btnHeight;
private String word;
private float scale;
private Animation anim;
private int tangelSound, whooshSound;
private SoundPool mSoundPool2;
private int soundMusic;
private boolean startAnim = false;
private LayoutAnimationController controller;
#Override
public void onStart(){
super.onStart();
if (!word.equals("suoh") && startAnim) {
anim = AnimationUtils.loadAnimation(getActivity(), R.anim.theater);
anim.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
mSoundPool2.play(whooshSound, soundMusic, soundMusic, 0, 0, 1);
rl.setClickable(false);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
// linearLayout.startLayoutAnimation();
startAnim = false;
Animation anim1 = AnimationUtils.loadAnimation(getActivity(), R.anim.blueword);
anim1.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
mSoundPool2.play(tangelSound, soundMusic, soundMusic, 0, wordLength, 0.5f);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
// rl.setClickable(true);
}
});
controller = new LayoutAnimationController(anim1, 0.5f);
linearLayout.setLayoutAnimation(controller);
linearLayout.setLayoutAnimationListener(new Animation.AnimationListener() {
public void onAnimationEnd(Animation _animation) {
rl.setClickable(true);
}
public void onAnimationRepeat(Animation _animation) {
}
public void onAnimationStart(Animation _animation) {
}
});
linearLayout.setVisibility(View.VISIBLE);
linearLayout.startLayoutAnimation();
}
});
rl.setVisibility(View.VISIBLE);
rl.startAnimation(anim);
}
}
public void falseClickable(){
rl.setClickable(false);
rl.setEnabled(false);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
face = Typefaces.get(getContext(), getContext().getText(R.string.font_droidsans).toString());
if (Build.VERSION.SDK_INT >= 21)
{
AudioAttributes attributes = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_GAME)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build();
mSoundPool2 = new SoundPool.Builder()
.setAudioAttributes(attributes)
.build();
} else {
mSoundPool2 = new SoundPool(5, AudioManager.STREAM_MUSIC, 0);
}
tangelSound = mSoundPool2.load(getActivity(), R.raw.tangel, 1);
whooshSound = mSoundPool2.load(getActivity(), R.raw.whoosh3, 1);
scale = getArguments().getInt("scale");
wordLheigh = getArguments().getInt("wordLheigh");
screenWidht = getArguments().getInt("screenWidht");
word = getArguments().getString("word");
wordLength = word.length();
soundMusic = getArguments().getInt("soundMusic");
startAnim = getArguments().getBoolean("startAnim");
//Log.e("TylyTaay", Integer.toString(FINAL));
margin = (int) (getResources().getDimension(R.dimen.word_btn_margin)+0.5f);
btnHeight = (int) (screenWidht / 10 - 4 * margin +0.5f);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_theater, container, false);
rl = (RelativeLayout) view.findViewById(R.id.theaterLayout);
TextView tv1 = (TextView) view.findViewById(R.id.textView1);
TextView tv2 = (TextView) view.findViewById(R.id.textView1);
tv1.setTypeface(face);
tv2.setTypeface(face);
if (!word.equals("suoh")){
linearLayout = (LinearLayout) view.findViewById(R.id.clonWordLayout);
RelativeLayout.LayoutParams lparams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, wordLheigh);
lparams.setMargins(0, screenWidht, 0, 0);
linearLayout.setLayoutParams(lparams);
setClon();
} else {
rl.setVisibility(View.VISIBLE);
}
return view;
}
#Override
public void onDestroy() {
super.onDestroy();
linearLayout.removeAllViews();
linearLayout = null;
RefWatcher refWatcher = MyApp.getRefWatcher(getActivity());
refWatcher.watch(this);
}
private void setClon()
{
Button btn;
for(int i = 0; i < wordLength; i++)
{
btn = new Button(getActivity());
char[] ch = {word.charAt(i)};
String st = new String(ch);
btn.setText(st);
btn.setGravity(Gravity.CENTER);
btn.setPadding(0, 0, 0, 0);
btn.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimension(R.dimen.word_btn_text_size));
btn.setBackgroundResource(R.drawable.btn_word_win);
btn.setTextColor(getResources().getColorStateList(R.color.dark_gray));
btn.setClickable(false);
btn.setTypeface(face);
LinearLayout.LayoutParams lparams = new LinearLayout.LayoutParams(btnHeight, btnHeight);
lparams.setMargins(margin, 0,margin, 0);
linearLayout.addView(btn, lparams); //Добавляем в LinearLayout
}
btn = null;
}
public void playSound(int nameSound ) {
if (soundMusic == 1)
mSoundPool2.play(nameSound,1,1,0,0,1);}
The sample code in MainActivity, which call the fragment:
private void rightAnswer()
{
if (imgZoom != null) {
imgZoomBack(wordL);
}
wordL.blockWord(false);
buttonL.blockBtn(false);
gridView.setOnItemClickListener(null);
//tf = new TheaterFragment(scale, wordLheigh, screenWidht, word, bar.tvDiamond, bar.tvLevel, bar.imageView, wordId);
if (tf == null) {
tf = new TheaterFragment();
}
if (args == null) {
args = new Bundle();
}
args.putFloat("scale", scale);
args.putInt("wordLheigh", wordLheight);
args.putInt("screenWidht", screenWidht);
args.putInt("soundMusic", soundOnOff);
args.putBoolean("startAnim", true);
args.putString("word", word);
//Log.e("TylyTaay", Integer.toString(wordId));
args.putInt("wordId", wordId);
tf.setArguments(args);
args = null;
getSupportFragmentManager()
.beginTransaction()
.add(R.id.frameLayout, tf)
.commit();
YoYo.with(Techniques.SlideOutDown)
.playOn(bar.tgDiamond);
YoYo.with(Techniques.SlideOutDown)
.playOn(bar.tgVolume);
YoYo.with(Techniques.SlideOutDown)
.playOn(bar.tvDiamond);
YoYo.with(Techniques.SlideOutDown)
.playOn(bar.tvLevel);
bar.imageView.setVisibility(View.VISIBLE);
YoYo.with(Techniques.SlideInDown)
.playOn(bar.imageView);}
I'm late for the response, this might be helpful for others.
As mentioned by #tsiro LeakCanary has its own bugs, you can go here for more details.
For your code,
getSupportFragmentManager()
.beginTransaction()
.add(R.id.frameLayout, tf)
.commit();
Here you are adding the fragment in FragmentManager but you are not removing it when the activity goes to background or when the fragment is changed/reinitialised.
Try removing the fragment from the fragment manager, if you are using .add().
You can use .replace() which calls .remove() and .add() implicitly.
I hope it helps.
i have just noticed that i take the same output in my application.Even though i double checked my app for possible memory leaks and after i resolve the actual point in my code where memory leak occured, i am still getting this message...you do not have to worry about it, probably it is a bug created by LeakCanary library...just ignore it as i did..

Is there any way make Snackbar persist among activity changes?

Although Snackbar is beautiful, it doesn't persist when changing activities. This is a bummer in scenarios where I would like to confirm that a message was sent using a Snackbar, before finishing the activity. I've considered pausing the code before exiting the activity, but have found that to be a bad practice.
If what I describe isn't possible, is there any type of material design toast message? Or a way to make a rectangular toast message; one with rounded edges of a smaller radius?
To create a Snackbar with the application context which is visible across multiple activities:
Get the WindowManager as system service
Create and add a FrameLayout (rootView) with type WindowManager.LayoutParams.TYPE_TOAST and WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL to the WindowManager
Wait until on FrameLayout.onAttachedToWindow() is called in the FrameLayout (rootView)
Get the window token of the FrameLayout (rootView) with View.getWindowToken()
Create a ContextThemeWrapper with the application context and a derived #style/Theme.AppCompat
Use the new context to create an additional FrameLayout (snackbarContainer)
Add this FrameLayout (snackbarContainer) with type WindowManager.LayoutParams.TYPE_APPLICATION_PANEL and flag WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
Wait until on View.onAttachedToWindow() is called in the FrameLayout (snackbarContainer)
Create the Snackbar like normal with the FrameLayout (snackbarContainer)
Set View.onDismissed() callback to the Snackbar and remove the FrameLayouts (rootView and snackbarContainer)
Show the snackbar Snackbar.show()
Here a working wrapper (NOTE: Swipe to dismiss is not working. Maybe some one else find the correct WindowManager.LayoutParams flags to receive touch events Fixed by CoordinatorLayout):
public class SnackbarWrapper
{
private final CharSequence text;
private final int duration;
private final WindowManager windowManager;
private final Context appplicationContext;
#Nullable
private Snackbar.Callback externalCallback;
#Nullable
private Action action;
#NonNull
public static SnackbarWrapper make(#NonNull Context applicationContext, #NonNull CharSequence text, #Snackbar.Duration int duration)
{
return new SnackbarWrapper(applicationContext, text, duration);
}
private SnackbarWrapper(#NonNull final Context appplicationContext, #NonNull CharSequence text, #Snackbar.Duration int duration)
{
this.appplicationContext = appplicationContext;
this.windowManager = (WindowManager) appplicationContext.getSystemService(Context.WINDOW_SERVICE);
this.text = text;
this.duration = duration;
}
public void show()
{
WindowManager.LayoutParams layoutParams = createDefaultLayoutParams(WindowManager.LayoutParams.TYPE_TOAST, null);
windowManager.addView(new FrameLayout(appplicationContext)
{
#Override
protected void onAttachedToWindow()
{
super.onAttachedToWindow();
onRootViewAvailable(this);
}
}, layoutParams);
}
private void onRootViewAvailable(final FrameLayout rootView)
{
final CoordinatorLayout snackbarContainer = new CoordinatorLayout(new ContextThemeWrapper(appplicationContext, R.style.FOL_Theme_SnackbarWrapper))
{
#Override
public void onAttachedToWindow()
{
super.onAttachedToWindow();
onSnackbarContainerAttached(rootView, this);
}
};
windowManager.addView(snackbarContainer, createDefaultLayoutParams(WindowManager.LayoutParams.TYPE_APPLICATION_PANEL, rootView.getWindowToken()));
}
private void onSnackbarContainerAttached(final View rootView, final CoordinatorLayout snackbarContainer)
{
Snackbar snackbar = Snackbar.make(snackbarContainer, text, duration);
snackbar.setCallback(new Snackbar.Callback()
{
#Override
public void onDismissed(Snackbar snackbar, int event)
{
super.onDismissed(snackbar, event);
// Clean up (NOTE! This callback can be called multiple times)
if (snackbarContainer.getParent() != null && rootView.getParent() != null)
{
windowManager.removeView(snackbarContainer);
windowManager.removeView(rootView);
}
if (externalCallback != null)
{
externalCallback.onDismissed(snackbar, event);
}
}
#Override
public void onShown(Snackbar snackbar)
{
super.onShown(snackbar);
if (externalCallback != null)
{
externalCallback.onShown(snackbar);
}
}
});
if (action != null)
{
snackbar.setAction(action.text, action.listener);
}
snackbar.show();
}
private WindowManager.LayoutParams createDefaultLayoutParams(int type, #Nullable IBinder windowToken)
{
WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
layoutParams.format = PixelFormat.TRANSLUCENT;
layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
layoutParams.gravity = GravityCompat.getAbsoluteGravity(Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM, ViewCompat.LAYOUT_DIRECTION_LTR);
layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
layoutParams.type = type;
layoutParams.token = windowToken;
return layoutParams;
}
#NonNull
public SnackbarWrapper setCallback(#Nullable Snackbar.Callback callback)
{
this.externalCallback = callback;
return this;
}
#NonNull
public SnackbarWrapper setAction(CharSequence text, final View.OnClickListener listener)
{
action = new Action(text, listener);
return this;
}
private static class Action
{
private final CharSequence text;
private final View.OnClickListener listener;
public Action(CharSequence text, View.OnClickListener listener)
{
this.text = text;
this.listener = listener;
}
}
}
EDIT
Once SnackbarWrapper is defined you can use it like this:
final SnackbarWrapper snackbarWrapper = SnackbarWrapper.make(getApplicationContext(),
"Test snackbarWrapper", Snackbar.LENGTH_LONG);
snackbarWrapper.setAction(R.string.snackbar_text,
new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(), "Action",
Toast.LENGTH_SHORT).show();
}
});
snackbarWrapper.show();
If you don't have a theme, you can quickly define one in styles.xml:
<style name="FOL_Theme_SnackbarWrapper" parent="#style/Theme.AppCompat">
<!--Insert customization here-->
</style>
EDIT
For those on Android Oreo getting Bad Token Exception, change TYPE_TOAST to TYPE_APPLICATION_OVERLAY. This is due to Android Oreo implementing special permissions to draw over applications. You can ask for this permissions using:
if(!Settings.canDrawOverlays(Activity.this){
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, URI.parse("package:" + getPackageName()));
startActivityForResult(intent, REQ_CODE);
}
If I understand correctly, you do this:
Activity A launch Activity B to send a message
Once message is send, you display a confirmation message
You go back to Activity A
You can use SnackBar to do that by using an ActivityResult (here is a StackOverflow post with how to use it)
Here are the steps:
Activity A launch Activity B with startActivityForResult
Do your stuff on Activity B
Set your result (check the link above to understand)
Finish Activity
In Activity A, get that code in OnActivityResult and display your
SnackBar with the proper message
This allow you do display a Snackar in Activity A corresponding to result of Activity B.
Hopes it can helps your problem
Just in case somebody needs to do this in Xamarin I have adapted the accepted answer which I found really helpful.
using Android.Content;
using Android.Graphics;
using Android.OS;
using Android.Runtime;
using Android.Support.Design.Widget;
using Android.Views;
using Android.Widget;
using System;
public class SnackbarWrapper
{
private readonly string text;
private readonly int duration;
private readonly IWindowManager windowManager;
private readonly Context appplicationContext;
private Snackbar.Callback externalCallback;
private SnackbarAction action { get; set; }
public static SnackbarWrapper make(Context applicationContext, string text, int duration)
{
return new SnackbarWrapper(applicationContext, text, duration);
}
private SnackbarWrapper(Context appplicationContext, string text, int duration)
{
this.appplicationContext = appplicationContext;
var wm = appplicationContext.GetSystemService(Context.WindowService);
// We have to use JavaCast instead of a normal cast
this.windowManager = wm.JavaCast<IWindowManager>();
this.text = text;
this.duration = duration;
}
public void Show()
{
WindowManagerLayoutParams layoutParams = createDefaultLayoutParams(WindowManagerTypes.Toast, null);
var frameLayout = new FrameLayout(appplicationContext);
frameLayout.ViewAttachedToWindow += delegate
{
//this.onAttachedToWindow();
onRootViewAvailable(frameLayout);
};
windowManager.AddView(frameLayout, layoutParams);
}
private void onRootViewAvailable(FrameLayout rootView)
{
var ctw = new ContextThemeWrapper(appplicationContext, Resource.Style.Base_Theme_AppCompat);
CoordinatorLayout snackbarContainer = new CoordinatorLayout(ctw);
snackbarContainer.ViewAttachedToWindow += delegate
{
onSnackbarContainerAttached(rootView, snackbarContainer);
};
windowManager.AddView(snackbarContainer, createDefaultLayoutParams(WindowManagerTypes.ApplicationPanel, rootView.WindowToken));
}
private void onSnackbarContainerAttached(View rootView, CoordinatorLayout snackbarContainer)
{
Snackbar snackbar = Snackbar.Make(snackbarContainer, text, duration);
snackbar.SetCallback(new SnackbarCallbackImpl(rootView, snackbarContainer, windowManager));
if (action != null)
{
snackbar.SetAction(action.Text, action.Listener);
}
snackbar.Show();
}
private WindowManagerLayoutParams createDefaultLayoutParams(WindowManagerTypes type, IBinder windowToken)
{
WindowManagerLayoutParams layoutParams = new WindowManagerLayoutParams();
layoutParams.Format = Format.Translucent;
layoutParams.Width = ViewGroup.LayoutParams.MatchParent;
/* Si ponemos aqui WrapContent en alguna ocasion en la que haya un action largo y el texto tambien, el snackbar puede volverse como loco
* asi que usamos MatchParent. Aun asi sucede que a veces se puede mostrar en una linea o en dos el mismo texto, pero al menos no hace el temblor loco que de la otra forma*/
layoutParams.Height = ViewGroup.LayoutParams.MatchParent;
layoutParams.Gravity = GravityFlags.CenterHorizontal | GravityFlags.Bottom;
layoutParams.Flags = WindowManagerFlags.NotTouchModal;
layoutParams.Type = type;
layoutParams.Token = windowToken;
return layoutParams;
}
public SnackbarWrapper SetCallback(Snackbar.Callback callback)
{
this.externalCallback = callback;
return this;
}
public SnackbarWrapper SetAction(string text, Action<View> listener)
{
action = new SnackbarAction(text, listener);
return this;
}
}//class
internal class SnackbarAction
{
public string Text { get; set; }
public Action<View> Listener { get; set; }
public SnackbarAction(string text, Action<View> listener)
{
Text = text;
Listener = listener;
}
}
internal class SnackbarCallbackImpl : Snackbar.Callback
{
public Snackbar.Callback externalCallback { get; set; }
View rootView;
CoordinatorLayout snackbarContainer;
IWindowManager windowManager;
public SnackbarCallbackImpl(View rootView, CoordinatorLayout snackbarContainer, IWindowManager windowManager)
{
this.rootView = rootView;
this.snackbarContainer = snackbarContainer;
this.windowManager = windowManager;
}
public override void OnShown(Snackbar snackbar)
{
base.OnShown(snackbar);
externalCallback?.OnShown(snackbar);
}
public override void OnDismissed(Snackbar snackbar, int evt)
{
base.OnDismissed(snackbar, evt);
// Clean up (NOTE! This callback can be called multiple times)
if (snackbarContainer.Parent != null && rootView.Parent != null)
{
windowManager.RemoveView(snackbarContainer);
windowManager.RemoveView(rootView);
}
externalCallback?.OnDismissed(snackbar, evt);
}
}
To have a rectangular Toast, set a rectangular background for the Toast or just set a different background color for the Toast.
Refer this post where it was posted as a problem. But it your case it is a possible solution.
UPDATE: See selected answer.
The best solution to my question is using a Timer after the presenting the Snackbar and then in the run() method of the timer, starting the activity.
Snackbar.show(); // Excluded make for brevity.
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
Intent chooseVideoIntent = new Intent(Intent.ACTION_GET_CONTENT); // Any type of content/file. Song, doc, video...
chooseVideoIntent.setType("video/*");
startActivityForResult(chooseVideoIntent, CHOOSE_VIDEO_REQUEST);
}
}, 2 * 1000);
UPDATE: I found that by using findViewById(android.R.id.content) as the view in Snackbar.make() the Snackbar persists among fragment changes.
Actually I just need to display a message and I don't need a onClickListener on the message.
If you just need to show a message look at "Myke Dev" answer in this thread which is the one I needed:
https://stackoverflow.com/a/34640942/9993413
(Don't give upvote to me, give upvote to "Myke Dev" which wrote the answer)
In user1185087 answer you must request permissions from user by opening settings and this, for me, isn't a good thing for user interactions, but I thinks is the only way if you want to show a snackbar with an onClickListener.
(Maybe you can use an activity with no background which launch a snackbar-like dialog, but it won't act just as a window_alert snackbar)

Android app with Google Maps Navigation and a text overlay

I have searched this issue for hours...
Is it possible to launch google maps navigation within my app and display a textview with some information on it? I have to create an app which passes the destination address to Maps Navigation and while Navigation is working show a textview with the cars model name on the bottom of the app. Is this doable?
Is it possible to launch google maps navigation within my app and display a textview with some information on it?
You cannot embed other applications in yours, and you cannot add your own widgets to some other application's UI.
Try this.
public class FloatingOverNewBooking extends Service {
private WindowManager windowManager;
private FrameLayout frameLayout;
private String str_ride_id;
public static final String BROADCAST_ACTION = "com.yourpackage.YourActivity";
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
timerLocation = new Timer();
createFloatingBackButton();
}
Timer timerLocation;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// to receive any data from activity
str_ride_id = intent.getStringExtra("RIDE_ID");
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
if (frameLayout != null) {
//((WindowManager) getSystemService(WINDOW_SERVICE)).removeView(frameLayout);
windowManager.removeView(frameLayout);
frameLayout = null;
}
timerLocation.cancel();
}
private void createFloatingBackButton() {
ClientLocatedActivity.isFloatingIconServiceAlive = true;
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_PHONE,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
WindowManager.LayoutParams windowManagerParams = new WindowManager.LayoutParams(WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY ,
WindowManager.LayoutParams. FLAG_DIM_BEHIND, PixelFormat.TRANSLUCENT);
params.gravity = Gravity.LEFT | Gravity.CENTER_VERTICAL;
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
frameLayout = new FrameLayout(this);
LayoutInflater layoutInflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
// Here is the place where you can inject whatever layout you want in the frame layout
layoutInflater.inflate(R.layout.share_new_booking_alert, frameLayout);
final TextView txtName = (TextView) frameLayout.findViewById(R.id.txtName);
Button backOnMap = (Button) frameLayout.findViewById(R.id.dialog_button);
if(!ObjectUtility.isNullOrEmpty(Config.Share.newPassenger)){
txtName.setText(Config.Share.newPassenger.getUsername());
}
backOnMap.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
am.killBackgroundProcesses("com.google.android.apps.maps");
//MainActivity.getInstance().getShareRideDataById("go");
FloatingOverNewBooking.this.stopSelf();
ClientLocatedActivity.isFloatingIconServiceAlive = false;
} catch (Exception e) {
e.printStackTrace();
}
}
});
windowManager.addView(frameLayout, windowManagerParams);
}
}

Categories

Resources