My problem that my live wallpaper displays some ad in the settings screen in a linearlayout (it works perfectly), but when I send it to background (e.g.: press home button), it seems that the adview is not destroyed and that causes higher cpu usage (25-50%). If I turn off my internet connection or just remove the ad displaying code it works without spinning.
After I investigated the question, I found (https://developers.google.com/mobile-ads-sdk/docs/admob/fundamentals) that I had to destroy the adview at onDestroy, but my problem is that this should happen in the activity where I can't reach the adview. And I don't know how I could solve it so if you have any idea please help me.
My code:
AdPreference.java:
public class AdPreference extends Preference {
public AdPreference(Context context, AttributeSet attrs, int defStyle) {super (context, attrs, defStyle);}
public AdPreference(Context context, AttributeSet attrs) {super(context, attrs);}
public AdPreference(Context context) {super(context);}
public AdView adView;
#Override
protected View onCreateView(ViewGroup parent) {
// this will create the linear layout defined in ads_layout.xml
View view = super.onCreateView(parent);
// the context is a PreferenceActivity
Activity activity = (Activity)getContext();
// Create the adView
adView = new AdView(activity, AdSize.BANNER, "mybanner");
((LinearLayout)view).addView(adView);
// Initiate a generic request to load it with an ad
AdRequest request = new AdRequest();
adView.loadAd(request);
return view;
}
and my activity:
public class Prefs extends PreferenceActivity
implements SharedPreferences.OnSharedPreferenceChangeListener {
#Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
addPreferencesFromResource(R.xml.wallpaper_settings);
}
#Override
protected void onDestroy()
{
getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
super.onDestroy();
}
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)
{
} }
I could be wrong because I am not the best at this, but it looks like you might be missing a
#Override
public void onDestroy() {
if (adView != null) {
adView.destroy();
}
super.onDestroy();
}
Or something like that. I mean, I don't see really anywhere that you tell the live wallpaper to stop the ad requests.
Like I said, I could be wrong, but those are my beliefs on the matter at hand.
Related
I found this link that states how I could make the glow effect on my ImageButton. So whenever the user press the ImageButton the onTouchEvent() function is called and there I call the setImageBitmap() function. The problem is this function (setImageBitmap()) seems to have no effect at all.
What works:
1) So far I extended the ImageButton as below
// Pen.java
public class Pen extends ImageButton {
public Pen(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
System.out.println("Now I am setting Pen");
return true;
}
}
Then inside Activity I create Pen (custom ImageButton) instance, define setGlow() and call setImageBitmap() from instance of Pen.
//MainActivity.java
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Pen myImgbutton;
myImgbutton = (Pen) findViewById(R.id.pen);
myImgbutton.setImageBitmap(setGlow(R.drawable.pen));
}
}
public Bitmap setGlow(int resourceId) {
......
}
What doesn't work:
1) All same as above ( extending a ImageButton in android ), but this time I am calling the
setImageBitmap function from inside onTouchEvent(). For this case I have define setGlow function in inside Pen.java
// Pen.java
public class Pen extends ImageButton {
public Pen(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
System.out.println("Now I am setting Pen");
// Here I say to apply the glow effect to the image
setImageBitmap(setGlow(R.drawable.pen));
return true;
}
public Bitmap setGlow(int resourceId) {
....
}
}
Then in xml file I do :
.....
<com.example.testsetimagebmp.Pen
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/pen"
android:background="#drawable/pen" />
....
Finally in MainActivity
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
// ....
}
I think this might be the classic out of memory issue. You can try to use the bitmap of the launcher icon if you want to check whether this is true:
public class Pen extends ImageButton {
public Pen(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
System.out.println("Now I am setting Pen");
// Here I say to apply the glow effect to the image
setImageBitmap(setGlow(R.mipmap.ic_launcher));
return true;
}
public Bitmap setGlow(int resourceId) {
....
}
}
If this is the problem check this link.
You can't do that because you will out of memory if you put setImageBitmap(setGlow(R.drawable.pen)) in onTouchEvent.
onTouchEvent will be triggered serval times per second.And you will create serval bitmaps in memory per second.It will out of memory before you setImageBitmap successfully.
I built the project as you post, but it works fine. It sets the Bitmap correctly. So maybe the getGlow() method doesn't work well. Make some Logs as below
public Bitmap setGlow(int resourceId) {
Bitmap bm = BitmapFactory.decodeResource(getResources(),resourceId);
Log.e("tag", "Size: " + bm.getByteCount());
return bm;
}
then check whether the return is right.
I'd like to know how to create buttons, textViews etc. in an Activity, which doesn't use an xml file as ContentView.
What I mean:
Main Class:
protected void onCreate(Bundle savedInstanceState)
{
//...
puzzleView = new PuzzleView(this);
setContentView(puzzleView);
}
The PuzzleView class:
public class PuzzleView extends View
{
private final Game game;
public PuzzleView(Context context)
{
super(context);
this.game = (Game) context;
setFocusable(true);
setFocusableInTouchMode(true);
}
#Override
protected void onDraw(Canvas canvas)
{
// drawing some things here
}
}
You probably want to set your content view to a class that extends ViewGroup, then add views to that class. Layouts are probably what you're after, in particular. Here are some tutorials:
http://blogspot.arcintechnologies.com/android/generate-android-layout-programmatically/
http://mainerrors.blogspot.ca/2011/02/programmatically-creating-layout-part-1.html
When I build a View in Android dynamically I have to add it to a "parent" ViewGroup by calling
myLinearLayout.addView(myView);
I know that I can supervise the ViewGroup for any children to be added via the excellent onHierarchyChangeListener, but in my case I need the feedback in the View itself. Therefore my question is:
Is there something like a View.onAddedToParent() callback or a listener that I can build on?
To make things very clear: I want the view to handle everything on its own, I am aware of the fact that I could catch the event in the "parent" and then notify the view about things, but this is not desired here. I can only alter the view
Edit: I just found onAttachStateChangeListener and it would seem to work for most situations, but I'm wondering if this is really the correct solution. I'm thinking a View might just as well be passed on from one ViewGroup to another without being detached from the window. So I would not receive an event even though I want to. Could you please elaborate on this if you have insight?
Thanks in advance
You can create custom view and do your stuff in its onAttachedToWindow
public class CustomView extends View {
public CustomView(Context context) {
super(context);
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
Log.d("CustomView", "onAttachedToWindow called for " + getId());
Toast.makeText(getContext(), "added", 1000).show();
}
}
If you want to ensure that your customview added to correct viewgroup which you want
#Override
protected void onAttachedToWindow() {
// TODO Auto-generated method stub
super.onAttachedToWindow();
if(((View)getParent()).getId()== R.id.relativelayout2)
{
Log.d("CustomView","onAttachedToWindow called for " + getId());
Toast.makeText(context, "added", 1000).show();
}
}
According to the Android source code, a view can't be moved to another layout unless removeView() is called first on its parent, and if you look at the code of removeView(), it calls removeViewInternal(), which in turn calls an overload of removeViewInternal(), which, on this line calls view.dispatchDetachedFromWindow(), which, based on the Android source code on this line calls onDetachedFromWindow(). Then the view gets added using addView(), which calls onAttachedToWindow() in the same way.
In my opion you want like this;
CreateViews;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
layout.setOnHierarchyChangeListener(new OnHierarchyChangeListener() {
#Override
public void onChildViewRemoved(View parent, View child) {
Log.e("View","removed");
if(child instanceof CustomButton){
CustomButton button = (CustomButton)child;
button.addListener();
}
}
#Override
public void onChildViewAdded(View parent, View child) {
Log.e("View","added");
if(child instanceof CustomButton){
CustomButton button = (CustomButton)child;
button.addListener();
}
}
});
for(int i = 0; i < 10; ++i){
CustomButton view = new CustomButton(this);
view.setText("Button "+i);
layout.addView(view, new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
view.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
layout.removeViewAt(layout.getChildCount()-1);
}
});
}
setContentView(layout);
}
Listener;
public interface OnAddedListener {
public void addListener();
}
CustomButton class;
public class CustomButton extends Button implements OnAddedListener{
public CustomButton(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public CustomButton(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public CustomButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
#Override
public void addListener() {
Log.e("","In button add listener");
}
}
I have a class called HeaderView which I use all over my application:
public HeaderView(Context context, AttributeSet attrs) {
super(context, attrs);
ctx = context;
commonApi = AAALifestyleApplication.commonApi;
user = commonApi.getCurrentUser();
inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.header_view, this, true);
((ImageView)this.findViewById(R.id.logo)).setOnClickListener(this);
inboxButton = (ImageView) this.findViewById(R.id.inbox_image);
inboxButton.setOnClickListener(this);
inboxButton2 = (ImageView) this.findViewById(R.id.inbox_image2);
inboxButton2.setOnClickListener(this);
requestsButton = (ImageView) this.findViewById(R.id.requests_image);
requestsButton.setOnClickListener(this);
requestsButton2 = (ImageView) this.findViewById(R.id.requests_image2);
requestsButton2.setOnClickListener(this);
progressBar = (ProgressBar) this.findViewById(R.id.header_progress_bar);
if (!showProgressBar) {
progressBar.setVisibility(INVISIBLE);
}
AAAAsyncTask.setProgressBarListener(this);
refreshView();
}
public static void refreshView(){
SharedPreferences sp = ctx.getSharedPreferences("HeaderView", Context.MODE_PRIVATE);
int newMessages = sp.getInt("newMessagesCount", 0);
int newRequests = sp.getInt("newRequestsCount", 0);
if(newMessages > 0){
Log.d("daim", "new messages!");
inboxButton.setVisibility(View.GONE);
inboxButton2.setVisibility(View.VISIBLE);
}
else{
Log.d("daim", "no new messages!");
inboxButton.setVisibility(View.VISIBLE);
inboxButton2.setVisibility(View.GONE);
}
if(newRequests > 0){
requestsButton.setVisibility(View.GONE);
requestsButton2.setVisibility(View.VISIBLE);
}
else{
requestsButton.setVisibility(View.VISIBLE);
requestsButton2.setVisibility(View.GONE);
}
}
In my Activity, this HeaderView gets called onCreate cause its specified in the XML, and also in onResume() like this:
#Override
public void onResume(){
super.onResume();
HeaderView.refreshView();
}
In the onCreate() method this works correctly, but onResume() I get the right amount of messages and I even logged this, so I know for sure that "no new messages" is printed, but the setVisibility() method doesn't update at all, and instead I see the previous ImageView when I had "new messages".
Please help, I've tried using handler with a thread to see if that was the problem, but it still remains this way.
You should instantiate your view, and make the refreshView non-static.
Declare your Activity like this:
public class YourActivity extends Activity {
private HeaderView mHeaderView;
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
mHeaderView = new HeaderView(this);
}
#Override
public void onResume(){
super.onResume();
mHeaderView.refreshView();
}
}
And remove the static keyword in your refreshView method declaration.
I made a simple extension of CheckBoxPreference so that I could have my own custom view with an image icon to the left of the title. The code is below:
public class CustomCheckBoxPreference extends CheckBoxPreference {
private Drawable icon;
public CustomCheckBoxPreference(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray arr = context.obtainStyledAttributes(attrs, R.styleable.CustomCheckBoxPreference, 0, 0);
icon = arr.getDrawable(R.styleable.CustomCheckBoxPreference_icon);
setLayoutResource(R.layout.custom_checkbox_pref);
}
#Override
protected void onBindView(View view) {
super.onBindView(view);
ImageView prefsIcon = (ImageView) view.findViewById(R.id.prefs_icon);
prefsIcon.setImageDrawable(icon);
}
The problem is that for some reason the OnPreferenceChangeListener I set to any CustomCheckboxPreference has no effect and is not stored. I tried overriding some of the android methods for the implementation calling super and then printing a line to see what gets called. Notably callChangeListener does not get called. It is this method that leads to the callback for onPreferenceChanged. I tried throwing in a call to onPreferenceChanged inside of setChecked just to see what would happen and the OnPreferenceChangeListener is null:
getOnPreferenceChangeListener().onPreferenceChange(this, checked);
This is how I set the preferencechangelistener:
mTwitterPref.setChecked(!mTwitter.needsAuth());
mTwitterPref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
System.out.println("Twitter Preference Changed!");
if ((Boolean) newValue) {
if (mTwitter.needsAuth()) {
System.out.println("We Need To Login To Twitter!");
IntentUtils.startActivityForResult(ProfileAccountsActivity.this,
TwLoginActivity.class, ACTIVITY_OAUTH);
}
} else {
showDialog(DIALOG_LOGOUT_TWITTER);
}
return false;
}
});
I am a bit confused as to why the preferencechangelistener is not working properly as I only overwrite onBindView and the constructor; I call super in both. Any thoughts?
Set android:focusable="false" and android:clickable="false" on the CheckBox:
<CheckBox
android:id="#+android:id/checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusable="false"
android:clickable="false" />
More info on this thread: Clickable rows on custom ArrayAdapter
I had the same issue with custom button. I tried the solution provided by #jeanh and it works. But my button was not pressed, only area around it was highlighted. Moreover, what if you have a few buttons? Obviously, that this solution won't work. So, I decided to dig deeper and my solution was below:
xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/widget_frame" android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingLeft="15dp"
android:paddingTop="5dp"
android:paddingRight="10dp"
android:paddingBottom="5dp"
>
<!-- define my button -->
<Button android:id="#android:id/title"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="17sp"
android:typeface="sans"
android:textStyle="bold"
android:textColor="#000000"
></Button>
</RelativeLayout>
Java class:
public class ButtonPreference extends Preference {
private final String TAG = getClass().getName();
public interface ButtonListener {
public void onCustomClick();
}
public ButtonListener buttonListener;
public void setButtonListener(ButtonListener buttonListener){
this.buttonListener = buttonListener;
}
public ButtonPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ButtonPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected View onCreateView(ViewGroup parent){
RelativeLayout layout = null;
try {
LayoutInflater mInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
layout = (RelativeLayout)mInflater.inflate(R.layout.button_preference, parent, false);
//FIND OUR BUTTON IN LAYOUT
Button button = (Button) layout.findViewById(android.R.id.title);
if(button!=null){
Log.e(TAG, "button found");
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(buttonListener!=null){
buttonListener.onCustomClick(); //INVOKE OUR EVENT!
}
}
});
}
}
catch(Exception e)
{
Log.e(TAG, "Error creating info preference", e);
}
return layout;
}
}
HOW TO USE IT? Simple!
public class WallpaperSettings extends PreferenceActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.prefs);
ButtonPreference defaultSettingsButton = (ButtonPreference) findPreference(EngineCore.pref+"defaultSettings");
defaultSettingsButton.setButtonListener(new ButtonListener() {
#Override
public void onCustomClick() {
Gdx.app.log("ButtonListener", "onCustomClick");
}
});
}
}
I hope it helps someone else.
I found solution !
In my case, I extends DialogPreference to my custom Dialog class,
public class SvDialogPreference extends DialogPreference
I also confuse, because in PreferenceFragment, onPreferenceChange never worked.
SvDialogPreference pref= (SvDialogPreference) findPreference("mainKey");
if( pref != null ) {
pref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
// Never execute !
}}
To resolve this. I called "super.callChangeListener" in onDialogClosed.
public class SvDialogPreference extends DialogPreference{
....
#Override
protected void onDialogClosed(boolean positiveResult) {
double InputValue = Double.parseDouble(KEY.getText().toString());
super.callChangeListener(InputValue);
super.onDialogClosed(positiveResult);
}
Now, onPreferenceChange worked fine !