View distorted/blurred while using admob/amazon adds in Nexus 4 - android

In Nexus 4, when showing adds (admob or amazon's), a view that is added and moved touching the screen becomes distorted. If ads are not shown, there is no problem with the view.
There isn't any problem either in the emulator or in a galaxy IV.
I think that the problem could be somewhat related to the chrome renderer and its use of the egl driver, but no idea how to solve it.
A test view code with admob:
public class TestAdmob extends ViewGroup {
private AdView adView;
private Rect drawRect;
private Test1 myView;
public TestAdmob(Activity context, String adUnitId) {
super(context);
myView = new Test1(context);
drawRect = new Rect(0, 0, 400, 400);
adView = new AdView(context);
adView.setAdSize(AdSize.SMART_BANNER);
adView.setAdUnitId(adUnitId);
adView.setAdListener(new AdListener() {
public void onAdLoaded() {
Log.d("Admob", "onAdLoaded");
requestLayout();
}
public void onAdFailedToLoad(int errorCode) { Log.d("Admob", "failedToLoad " + errorCode); }
public void onAdOpened() { Log.d("Admob", "adOpened"); }
public void onAdClosed() { Log.d("Admob", "adClosed"); }
public void onAdLeftApplication() { Log.d("Admob", "adLeftApp"); }
});
AdRequest adRequest = new AdRequest.Builder()
.addTestDevice(AdRequest.DEVICE_ID_EMULATOR)
.build();
addView(adView);
adView.loadAd(adRequest);
}
private int getHeightAd() {
try { return adView.getAdSize().getHeightInPixels(adView.getContext()); }
catch (Exception e) {
e.printStackTrace();
return 200;
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
adView.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(getHeightAd(), MeasureSpec.EXACTLY));
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
adView.layout(l, 0, r, getHeightAd());
myView.layout(drawRect.left, drawRect.top, drawRect.right, drawRect.bottom);
}
#Override public boolean onTouchEvent(MotionEvent event) {
drawRect.offsetTo((int)event.getX()-drawRect.width()/2, (int)event.getY()-drawRect.height()/2);
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
addView(myView);
break;
case MotionEvent.ACTION_MOVE:
requestLayout();
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_OUTSIDE:
removeView(myView);
default:
break;
}
return true;
}
private class Test1 extends View {
Path path = new Path();
Bitmap bitmap;
public Test1(Context context) {
super(context);
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.anImage);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
path.moveTo(0, 0);
path.lineTo(getWidth(), 0);
path.lineTo(getWidth()/2, getHeight());
path.moveTo(0, 0);
canvas.clipPath(path);
canvas.drawBitmap(bitmap, 0, 0, null); }
}
}
The distorted view when showing ads:
and when not, as it should be:

Finally I found a solution. Based on this post, I modified the code like this (added the setLayer line):
...
}
private class Test1 extends View {
Path path = new Path();
Bitmap bitmap;
public Test1(Context context) {
super(context);
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable. anImage);
}
...

Related

Simple game works on tablet but sometimes lags on phone

I'm developing simple Android game, but I'm running into problems while testing it. When I run it on Lenovo Tab3 7 tablet (Android 5.0.1 ) or LG P880 phone (Android 4.0.3) it works fine. When I run it on Samsung S7 phone (Android 7.0) game usually runs fine. What I mean by this is that I can run it 10 times in a row with no problems, but sometimes game halts for 5-30 seconds or stops responding. This usually happens during starting of new Activity or very shortly after it.
Game has 4 Activities which use extended SurfaceView as layout. All SurfaceViews implement Runnable. Activities are: Splash screen (noHistory = "true" in Manifest), Menu, Difficulty choice and Game.
I use only mdpi drawables and scale them proportionally to all screen sizes. Bitmaps are loaded using BitmapFactory.decodeResource with BitmapFactory.Options inDensity = 1, inScaled = false.
When the problem occurs logcat shows only garbage collection. Sometimes game "pauses" (no taps are registered) for 5-30 seconds and resumes normally, sometimes it has to be restarted due to no response. I feel like game stops collecting input for some reason. Input is handled by overriding onTouchEvent and checking if ACTION_UP is within tapped image bounds. As I said, this happens only on S7 (I tried it on two phones), not on tablet or P880, so I'm thinking it might be something to do with Nougat or me forcing lower density on the phone.
So, since I'm running out of ideas what could be causing this and me being new to Android game development, does anyone know/have any idea where I should be looking for solution? Is there anything Nougat-specific I should be setting/checking? Does forcing pixel density affect device performance in any way?
Edit 1
globalApp
public class globalApp extends Application {
SoundPool soundPool;
SoundPool.Builder soundPoolBuilder;
AudioAttributes audioAttributes;
AudioAttributes.Builder audioAttributesBuilder;
int soundTap, soundCorrect, soundIncorrect, soundVictory, soundDefeat;
int soundBarrelVerySlow, soundBarrelSlow, soundBarrelNormal, soundBarrelFast, soundBarrelVeryFast;
#Override
public void onCreate() {
super.onCreate();
}
public void buildSoundPool(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
audioAttributesBuilder = new AudioAttributes.Builder();
audioAttributesBuilder.setUsage(AudioAttributes.USAGE_GAME);
audioAttributesBuilder.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION);
audioAttributes = audioAttributesBuilder.build();
soundPoolBuilder = new SoundPool.Builder();
soundPoolBuilder.setMaxStreams(2);
soundPoolBuilder.setAudioAttributes(audioAttributes);
soundPool = soundPoolBuilder.build();
}
else {
soundPool = new SoundPool(1, AudioManager.STREAM_MUSIC, 0);
}
}
public void loadSounds(){
soundBarrelVerySlow = soundPool.load(this,R.raw.very_slow_move, 1);
soundBarrelSlow = soundPool.load(this, R.raw.slow_move, 1);
soundBarrelNormal = soundPool.load(this, R.raw.slow_move, 1);
soundBarrelFast = soundPool.load(this,R.raw.fast_move, 1);
soundBarrelVeryFast = soundPool.load(this,R.raw.very_fast_move, 1);
soundTap = soundPool.load(this, R.raw.tap_sound, 1);
soundCorrect = soundPool.load(this, R.raw.correct, 1);
soundIncorrect = soundPool.load(this, R.raw.incorrect, 1);
soundVictory = soundPool.load(this, R.raw.victory, 1);
soundDefeat = soundPool.load(this, R.raw.defeat, 1);
}
public void playTap(){
soundPool.play(soundTap, 1, 1,1, 0, 1);
}
public void playCorrect(){
soundPool.play(soundCorrect, 1, 1,1, 0, 1);
}
public void playIncorrect(){
soundPool.play(soundIncorrect, 1, 1,1, 0, 1);
}
public void playVictory(){
soundPool.play(soundVictory, 1, 1,1, 0, 1);
}
public void playDefeat(){
soundPool.play(soundDefeat, 1, 1,1, 0, 1);
}
public void playBarrelVerySlow(){soundPool.play(soundBarrelVerySlow, 1, 1, 1, 0, 1);}
public void playBarrelSlow(){soundPool.play(soundBarrelSlow, 1, 1, 1, 0, 1);}
public void playBarrelNormal(){
soundPool.play(soundBarrelNormal, 1, 1,1, 0, 1);
}
public void playBarrelFast(){soundPool.play(soundBarrelFast, 1, 1, 1, 0, 1);}
public void playBarrelVeryFast(){soundPool.play(soundBarrelVeryFast, 1, 1, 1, 0, 1);}
}
MenuItem
public class MenuItem {
private Bitmap bmp;
private Context context;
private Rect sourceRect;
private RectF destRect;
private int srcWidth;
private int srcHeight;
private int destW, destH;
private int x, y;
private int screenH;
public MenuItem(Context ctx, String bmpName, int w, int x, int y, int sX, int sY){
context = ctx;
BitmapFactory.Options bmpFOptions = new BitmapFactory.Options();
bmpFOptions.inDensity = 1;
bmpFOptions.inScaled = false;
int res = context.getResources().getIdentifier(bmpName, "drawable", ctx.getPackageName());
bmp = BitmapFactory.decodeResource(ctx.getResources(), res, bmpFOptions);
srcWidth = w;
srcHeight = bmp.getHeight();
this.x = x;
this.y = y;
screenH = sY;
sourceRect = new Rect(0,0, srcWidth, srcHeight);
destRect = new RectF();
setProportionalDestinationRect(sX, sY);
}
private void setProportionalDestinationRect(int scrX, int scrY) {
if (scrX != 1024 || scrY != 552){
float propX = (float)scrX/1024;
float propY = (float)scrY/600;
// All drawables are designed for 1024x600 screen
// if device screen is different, scale image proportionally
destW = (int)(srcWidth * propX);
destH = (int) (srcHeight * propY);
x = (int) (x*propX);
y = (int) (y*propY);
}
else {
destW = srcWidth;
destH = srcHeight;
}
destRect.set(x,y, x+destW,y+destH);
}
public void update(){
}
public Bitmap getBmp() {
return bmp;
}
public void setBmp(Bitmap bmp) {
this.bmp = bmp;
}
public Rect getSourceRect() {
return sourceRect;
}
public void setSourceRect(Rect sourceRect) {
this.sourceRect = sourceRect;
}
public RectF getDestRect() {
return destRect;
}
public void setDestRect(RectF destRect) {
this.destRect = destRect;
}
public boolean contains(int x, int y){
if (destRect.left <= x && destRect.right >= x)
if (destRect.top <= y && destRect.bottom >= y)
return true;
return false;
}
public void setY(int y) {
this.y = y;
if (screenH != 552){
float propY = (float)screenH/600;
y = (int) (y*propY);
}
destRect.set(x,y, x+destW,y+destH);
}
}
MainActivity
public class MainActivity extends Activity {
private boolean backPressedOnce = false;
long backPressedTime = 0;
private MainActivitySurface mainActivitySurface;
globalApp app;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Setting full screen
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
View decorView = getWindow().getDecorView();
int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
decorView.setSystemUiVisibility(uiOptions);
int x = getIntent().getIntExtra("screenWidth", 500);
int y = getIntent().getIntExtra("screenHeight", 500);
app = (globalApp) getApplication();
app.buildSoundPool();
app.loadSounds();
mainActivitySurface = new MainActivitySurface(this, app, x, y);
mainActivitySurface.setParentActivity(MainActivity.this);
setContentView(mainActivitySurface);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1001) {
if (resultCode == RESULT_OK) {
int result = data.getIntExtra("difficulty", 3);
mainActivitySurface.setResultDifficulty(result);
}
}
}
#Override
protected void onPause() {
super.onPause();
mainActivitySurface.pause();
}
#Override
protected void onResume() {
super.onResume();
backPressedOnce = false;
mainActivitySurface.resume();
}
#Override
public void onBackPressed() {
if (backPressedOnce && backPressedTime + 2000 > System.currentTimeMillis()) {
Process.killProcess(Process.myPid());
System.exit(1);
} else {
Toast.makeText(this, "Press back again to exit.", Toast.LENGTH_SHORT).show();
backPressedOnce = true;
}
backPressedTime = System.currentTimeMillis();
}
}
MainActivitySurface
public class MainActivitySurface extends SurfaceView implements Runnable {
private Context context;
private SurfaceHolder surfaceHolder;
private Canvas canvas;
private Thread thread = null;
volatile private boolean running = false;
private boolean surfaceCreated = false;
private Intent playIntent;
private Intent difficultyIntent;
// Screen size
private int screenWidth, screenHeight;
//Menu items
private MenuItem menuItemPlay, menuItemDifficulty, middleBarrel, bg;
private int difficulty = 3;
private Activity parentActivity;
private globalApp app;
public MainActivitySurface(Context ctx, globalApp a, int scrW, int scrH){
super(ctx);
context = ctx;
screenHeight = scrH;
screenWidth = scrW;
app = a;
surfaceHolder = getHolder();
surfaceHolder.addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceCreated(SurfaceHolder holder) {
surfaceCreated = true;
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
});
bg = new MenuItem(context, "main_activity_background_single", 1024, 0, 0, scrW, scrH);
menuItemPlay = new MenuItem(context, "menu_item_play_single", 233,(1024-233)/2,100, scrW, scrH);
menuItemDifficulty = new MenuItem(ctx, "menu_item_difficulty_single", 520,(1024 - 520)/2,400,scrW,scrH);
middleBarrel = new MenuItem(ctx, "middle_barrel_single", 323,(1024-323)/2,200,scrW,scrH);
playIntent = new Intent(context, GameActivity.class);
playIntent.putExtra("screenWidth", screenWidth);
playIntent.putExtra("screenHeight", screenHeight);
}
#Override
public void run() {
while (running){
draw();
}
}
private void draw() {
if(surfaceHolder.getSurface().isValid()){
canvas = surfaceHolder.lockCanvas();
canvas.drawBitmap(bg.getBmp(), bg.getSourceRect(), bg.getDestRect(), null);
canvas.drawBitmap(menuItemPlay.getBmp(), menuItemPlay.getSourceRect(), menuItemPlay.getDestRect(), null);
canvas.drawBitmap(menuItemDifficulty.getBmp(), menuItemDifficulty.getSourceRect(), menuItemDifficulty.getDestRect(), null);
canvas.drawBitmap(middleBarrel.getBmp(), middleBarrel.getSourceRect(), middleBarrel.getDestRect(), null);
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
public void resume(){
running = true;
thread = new Thread(this);
thread.start();
}
public void pause(){
running = false;
boolean retry = false;
while (retry) {
try {
thread.join();
retry = false;
} catch (InterruptedException e) {
e.printStackTrace();
Log.d("info", "MainActivitySurface: Error joining thread");
}
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction() & event.ACTION_MASK){
case MotionEvent.ACTION_UP:
if (menuItemPlay.contains((int) event.getX(), (int) event.getY())){
app.playTap();
parentActivity.startActivity(playIntent);
parentActivity.overridePendingTransition(0,0);
break;
}
if (menuItemDifficulty.contains((int) event.getX(), (int) event.getY())){
app.playTap();
difficultyIntent = new Intent(parentActivity, DifficultyActivity.class);
difficultyIntent.putExtra("screenWidth", screenWidth);
difficultyIntent.putExtra("screenHeight", screenHeight);
difficultyIntent.putExtra("difficulty", difficulty);
parentActivity.startActivityForResult(difficultyIntent, 1001);
parentActivity.overridePendingTransition(0, 0);
break;
}
}
return true;
}
public void setParentActivity(Activity act){
parentActivity = act;
}
public void setResultDifficulty(int diff){
difficulty = diff;
playIntent.putExtra("difficulty", difficulty);
}
}
DifficultyActivity
public class DifficultyActivity extends Activity {
private DifficultySurface surface;
private globalApp app;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Setting full screen
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
View decorView = getWindow().getDecorView();
int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
decorView.setSystemUiVisibility(uiOptions);
app = (globalApp) getApplication();
surface = new DifficultySurface(this, app, getIntent().getIntExtra("screenWidth", 500), getIntent().getIntExtra("screenHeight", 500));
setContentView(surface);
}
#Override
protected void onPause() {
super.onPause();
app.soundPool.release();
surface.pause();
overridePendingTransition(0, 0);
}
#Override
protected void onResume() {
super.onResume();
app.buildSoundPool();
app.loadSounds();
surface.resume();
}
}
DifficultySurface
public class DifficultySurface extends SurfaceView implements Runnable {
private SurfaceHolder surfaceHolder;
private Thread thread = null;
private Canvas canvas;
private Context context;
private globalApp app;
private boolean surfaceCreated = false;
private boolean running = false;
private MenuItem bgProp, arrowBarrel, okButton, diffVeryEasy, diffEasy, diffNormal, diffHard, diffVeryHard;
private int difficulty;
public DifficultySurface(Context ctx, globalApp a, int scrW, int scrH){
super(ctx);
context = ctx;
app = a;
surfaceHolder = getHolder();
surfaceHolder.addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceCreated(SurfaceHolder holder) {
surfaceCreated = true;
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
});
difficulty = ((Activity)context).getIntent().getIntExtra("difficulty", 3);
bgProp = new MenuItem(ctx, "difficulty_background", 1024, 0, 0, scrW, scrH);
diffVeryEasy = new MenuItem(ctx, "very_easy",796, 100, 100, scrW, scrH);
diffEasy = new MenuItem(ctx, "easy",796, 100, 200 , scrW, scrH);
diffNormal = new MenuItem(ctx, "normal",796, 100, 300, scrW, scrH);
diffHard = new MenuItem(ctx, "hard",796, 100, 400 , scrW, scrH);
diffVeryHard = new MenuItem(ctx, "very_hard",796, 100, 500, scrW, scrH);
okButton = new MenuItem(ctx, "ok_button", 100, 924, 500, scrW, scrH);
arrowBarrel = new MenuItem(ctx, "barrel_arrow", 100, 0, 100*difficulty, scrW, scrH);
}
#Override
public void run() {
while (running) {
if (surfaceCreated) {
update();
draw();
}
}
}
private void update() {
arrowBarrel.setY(difficulty*100);
}
private void draw() {
if (surfaceHolder.getSurface().isValid()){
canvas = surfaceHolder.lockCanvas();
canvas.drawBitmap(bgProp.getBmp(), bgProp.getSourceRect(), bgProp.getDestRect(), null);
canvas.drawBitmap(arrowBarrel.getBmp(), arrowBarrel.getSourceRect(), arrowBarrel.getDestRect(), null);
canvas.drawBitmap(diffVeryEasy.getBmp(), diffVeryEasy.getSourceRect(), diffVeryEasy.getDestRect(), null);
canvas.drawBitmap(diffEasy.getBmp(), diffEasy.getSourceRect(), diffEasy.getDestRect(), null);
canvas.drawBitmap(diffNormal.getBmp(), diffNormal.getSourceRect(), diffNormal.getDestRect(), null);
canvas.drawBitmap(diffHard.getBmp(), diffHard.getSourceRect(), diffHard.getDestRect(), null);
canvas.drawBitmap(diffVeryHard.getBmp(), diffVeryHard.getSourceRect(), diffVeryHard.getDestRect(), null);
canvas.drawBitmap(okButton.getBmp(), okButton.getSourceRect(), okButton.getDestRect(), null);
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction() & event.ACTION_MASK){
case MotionEvent.ACTION_UP:{
if (diffVeryEasy.contains((int) event.getX(), (int) event.getY())){
app.playTap();
difficulty = 1; }
if (diffEasy.contains((int) event.getX(), (int) event.getY())){
app.playTap();
difficulty = 2;
}
if (diffNormal.contains((int) event.getX(), (int) event.getY())){
app.playTap();
difficulty = 3;
}
if (diffHard.contains((int) event.getX(), (int) event.getY())){
app.playTap();
difficulty = 4;
}
if (diffVeryHard.contains((int) event.getX(), (int) event.getY())){
app.playTap();
difficulty = 5;
}
if (okButton.contains((int)event.getX(), (int) event.getY())){
app.playTap();
((Activity)context).getIntent().putExtra("difficulty", difficulty);
((Activity)context).setResult(Activity.RESULT_OK, ((Activity)context).getIntent());
((Activity)context).finish();
((Activity)context).overridePendingTransition(0, 0);
}
break;
}
}
return true;
}
public void pause(){
running = false;
boolean retry = true;
while (retry) {
try {
thread.join();
retry = false;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
((Activity)context).overridePendingTransition(0, 0);
}
public void resume(){
running = true;
thread = new Thread(this);
thread.start();
}
}
GameActivity
public class GameActivity extends Activity {
private GameSurface surface;
private globalApp app;
private int difficulty;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Setting full screen
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
View decorView = getWindow().getDecorView();
int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
decorView.setSystemUiVisibility(uiOptions);
difficulty = getIntent().getIntExtra("difficulty", 3);
app = (globalApp) getApplication();
surface = new GameSurface(this, app, getIntent().getIntExtra("screenWidth", 500), getIntent().getIntExtra("screenHeight", 500), difficulty);
surface.setParentActivity(this);
setContentView(surface);
}
#Override
protected void onPause() {
super.onPause();
app.soundPool.release();
surface.pause();
}
#Override
protected void onPostResume() {
super.onPostResume();
app.buildSoundPool();
app.loadSounds();
surface.resume();
}
#Override
protected void onStop() {
super.onStop();
surface.stop();
}
#Override
public void onBackPressed() {
super.onBackPressed();
finish();
}
}
Game halting happens either when I start DificultyActivity (I tap one MenuItem objects but nothing happens) or when I start GameActivity (game still shows MainActivity + MainActivitySurface).
Android Monitor show less than 40MB of allocated memory, so bitmaps shouldn't be the problem in my opinion. I tried recycling all bitmaps but the problem was present (that's why I opted to use only mdpi drawables; at first I used all pixel densities but tried lowering resources in case that was causing halts).
It is hard to find the problem without looking at the code. There's nothing nougat-specific way of handling the resources.
But android N claims to have a better memory management and since you are complaining a lot of garbage collections, it may be one of the cause. Make sure to recycle the unused bitmaps. And use RGB_565 as the preferred bitmap config which requires half memory than RGB_8888.
I have solved my problem. After posting question I came across this. It seems we had the same problem. When I slowed down drawing speed (using thread.sleep) there were no more issues.
Thanks to those who helped me.

Live wallpaper not change in Android device when set another live wallpaper

I am new to Android development and currently I am implementing Live wallpaper application.So, My question is How I can change live wallpaper when new live wallpaper is selected from the application.currently I am setting only one live wallpaper from my application but issue is that when I am selecting wallpaper from my application to set as wallpaper it is not change and display previously selected wallpaper.And when i am restarting my device then it will display.I am using Glide library to display Gif image.
Here this my WallpaperService class
public class GifPaperService extends WallpaperService {
static final String TAG = "gifService";
static final Handler gifHandler = new Handler();
int position;
boolean visible;
ImageAdapter img = new ImageAdapter();
Integer[] mThumb = img.mThumbIds;
#Override
public void onCreate() {
super.onCreate();
Log.v("Helllo", "...");
}
#Override
public Engine onCreateEngine() {
try {
return new GifEngine();
} catch (IOException e) {
Log.w(TAG, "Error creating engine", e);
stopSelf();
return null;
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.v("Hello..", ".....");
return super.onStartCommand(intent, flags, startId);
}
class GifEngine extends Engine {
private final Movie gif;
private final int duration;
private final Runnable runnable;
float scaleX;
float scaleY;
int when;
long start;
GifEngine() throws IOException {
MyPreferenceActivity myPref = new MyPreferenceActivity(getApplicationContext());
Log.i("Imageis... ", "Position.." + myPref.getGifImage());
position = myPref.getGifImage();
InputStream is = getResources().openRawResource(mThumb[position]);
Log.i("Imageposition...", "...." + mThumb[position]);
if (is == null) {
throw new IOException("Unable to open whoa.gif");
}
try {
gif = Movie.decodeStream(is);
duration = gif.duration();
} finally {
is.close();
}
when = -1;
runnable = new Runnable() {
#Override
public void run() {
animateGif();
}
};
}
#Override
public void onDestroy() {
super.onDestroy();
gifHandler.removeCallbacks(runnable);
}
#Override
public void onVisibilityChanged(boolean visible) {
super.onVisibilityChanged(visible);
if (visible) {
animateGif();
} else {
gifHandler.removeCallbacks(runnable);
}
}
#Override
public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
super.onSurfaceChanged(holder, format, width, height);
scaleX = width / (1f * gif.width());
scaleY = height / (1f * gif.height());
animateGif();
}
#Override
public void onOffsetsChanged(float xOffset, float yOffset,
float xOffsetStep, float yOffsetStep,
int xPixelOffset, int yPixelOffset) {
super.onOffsetsChanged(
xOffset, yOffset,
xOffsetStep, yOffsetStep,
xPixelOffset, yPixelOffset);
animateGif();
}
void animateGif() {
tick();
SurfaceHolder surfaceHolder = getSurfaceHolder();
Canvas canvas = null;
try {
canvas = surfaceHolder.lockCanvas();
if (canvas != null) {
gifCanvas(canvas);
}
} finally {
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
gifHandler.removeCallbacks(runnable);
if (isVisible()) {
gifHandler.postDelayed(runnable, 1000L / 25L);
}
}
void tick() {
if (when == -1L) {
when = 0;
start = SystemClock.uptimeMillis();
} else {
long diff = SystemClock.uptimeMillis() - start;
when = (int) (diff % duration);
}
}
void gifCanvas(Canvas canvas) {
canvas.save();
canvas.scale(scaleX, scaleY);
gif.setTime(when);
gif.draw(canvas, 0, 0);
canvas.restore();
}
#Override
public void onSurfaceDestroyed(SurfaceHolder holder) {
super.onSurfaceDestroyed(holder);
stopSelf();
gifHandler.removeCallbacks(runnable);
}
}
}
Activity class for setting wallpaper
setWallpaper.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (Build.VERSION.SDK_INT > 15) {
Intent intent = new Intent(WallpaperManager.ACTION_CHANGE_LIVE_WALLPAPER);
intent.putExtra(WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT, new ComponentName(mContext, GifPaperService.class));
startActivity(intent);
}
}
});
ImageAdapter:
public class ImageAdapter extends BaseAdapter {
static WallpaperInfo info;
private Context mContext;
public ImageAdapter() {
}
public int getCount() {
return mThumbIds.length;
}
public Object getItem(int position) {
return mThumbIds[position];
}
public long getItemId(int position) {
return 0;
}
public ImageAdapter(Context c) {
mContext = c;
}
public View getView(final int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null){
imageView = new ImageView(mContext);
imageView.setLayoutParams(new GridView.LayoutParams(200, 200));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(3, 3, 3, 3);
imageView.setMaxHeight(300);
imageView.setMaxWidth(300);
imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MyPreferenceActivity myPref = new MyPreferenceActivity(mContext);
myPref.setGifImage(position);
Intent intent = new Intent(mContext, FullScreenImage.class);
intent.putExtra("imageID", mThumbIds[position]);
/*intent.putExtra(EXTRA_LIVE_WALLPAPER_INTENT, intent);
intent.putExtra(EXTRA_LIVE_WALLPAPER_SETTINGS, info.getSettingsActivity());
intent.putExtra(EXTRA_LIVE_WALLPAPER_PACKAGE, info.getPackageName());*/
mContext.startActivity(intent);
}
});
Animation anim = AnimationUtils.loadAnimation(mContext.getApplicationContext(), R.anim.fly);
imageView.setAnimation(anim);
anim.start();
}
else{
imageView = (ImageView) convertView;
}
imageView.setImageResource(mThumbIds[position]);
return imageView;
}
public Integer[] mThumbIds = {
R.drawable.gpp1, R.drawable.gpp2,
R.drawable.gpp3,R.drawable.gpp4,
R.drawable.gpp5,R.drawable.gpp6,
R.drawable.gpp7,R.mipmap.h8,
R.mipmap.h9,R.mipmap.h10,
R.mipmap.h11,R.drawable.gp3,
R.drawable.gp2,R.drawable.gp,
R.drawable.onehalloween
};
}
If anyone know what is the problem.Tell me.
Thank in advance
For destroying previous wallpaper and setting new wallpaper,You have to Clear previous wallpaper like this,
In Your setWallpaper button click event use this code,
setWallpaper.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (Build.VERSION.SDK_INT > 16) {
WallpaperManager wallpaperManager = WallpaperManager.getInstance(getApplicationContext());
try {
wallpaperManager.clear();
} catch (IOException e) {
e.printStackTrace();
}
Intent intent = new Intent(WallpaperManager.ACTION_CHANGE_LIVE_WALLPAPER);
intent.putExtra(WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT, new ComponentName(mContext, GifPaperService.class));
Log.i("Intent....", "...." + intent);
startActivity(intent);
}
}
});
This is works for me...

ondraw taking too much ram in custom view repetition

I am designing a customview for the seats in the theater.For x large phones it is working smoothly.But in lower density devices it is hard to work with.
my customview.java
public class SeatView extends ImageView {
float dim;
int status;
Canvas canvas1;
boolean sela=false,ds=false,ua=false;
Bitmap selectedAvailableImage,deselectedAvailableImage,unavailableImage;
Drawable selectedAvailable,deselectedAvailable,unavailable;
SeatView seatView;
public SeatView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.getTheme().obtainStyledAttributes(attrs,R.styleable.SeatView,0, 0);
try {
dim = a.getDimension(R.styleable.SeatView_dim, 20f);
status=a.getInt(R.styleable.SeatView_status,1);
selectedAvailableImage=BitmapFactory.decodeResource(getResources(),R.drawable.seat_selected);
deselectedAvailableImage=BitmapFactory.decodeResource(getResources(),R.drawable.seat_available);
unavailableImage=BitmapFactory.decodeResource(getResources(),R.drawable.seat_unavailable);
selectedAvailable=getResources().getDrawable(R.drawable.seat_selected);
deselectedAvailable=getResources().getDrawable(R.drawable.seat_available);
unavailable=getResources().getDrawable(R.drawable.seat_unavailable);
//selectedAvailable.setBounds(100,100,100,100);
//deselectedAvailable.setBounds(10,10,10,10);
//unavailable.setBounds(10,10,10,10);
} finally {
a.recycle();
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction()==MotionEvent.ACTION_UP){
if(status==0){
status=1;
invalidate();
}else if(status==1){
status=0;
invalidate();
}
}
return true;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(50,50);
}
public void setAvailable(){
status=1;
invalidate();
}
public void setDisabled(){
status=2;
invalidate();
}
public void setSelected(){
status=0;
invalidate();
}
public int getSeatStatus(){
return status;
}
public void init(Canvas canvas){
switch (status){
case 0:
//sela=true;ds=false;ua=false;
//setImageDrawable(selectedAvailable);
canvas.drawBitmap(selectedAvailableImage,0,0,null);
break;
case 1:
//sela=false;ds=true;ua=false;
//setImageDrawable(deselectedAvailable);
canvas.drawBitmap(deselectedAvailableImage,0,0,null);
break;
case 2:
//sela=false;ds=false;ua=true;
//setImageDrawable(unavailable);
canvas.drawBitmap(unavailableImage,0,0,null);
break;
default: //setImageDrawable(deselectedAvailable);
canvas.drawBitmap(deselectedAvailableImage,0,0,null);
break;
}
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
init(canvas);
}
}
and my mainactivity.java
public class MainActivity extends AppCompatActivity {
ImageView imageView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//ButterKnife.bind(this);
TableLayout tableLayout=(TableLayout)findViewById(R.id.tblelay);
// Toast.makeText(getApplicationContext(),seatView.getSeatStatus()+"",Toast.LENGTH_LONG).show();
//LinearLayout relativeLayout=(LinearLayout) findViewById(R.id.tblelay);
for (int j=0;j<20;j++){
TableRow tableRow=new TableRow(this);
for (int i=1;i<20;i++){
SeatView seatView=new SeatView(this,null);
seatView.setAvailable();
seatView.setId(i);
if(i%5==0){
seatView.setVisibility(View.INVISIBLE);
}
if(seatView.getParent()!=null)
((ViewGroup)seatView.getParent()).removeView(seatView); // <- fix
if(tableRow.getParent()!=null)
((ViewGroup)tableRow.getParent()).removeView(tableRow);
/* if(i>0){
RelativeLayout.LayoutParams layoutParams=new Rela tiveLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
layoutParams.addRule(RelativeLayout.RIGHT_OF, (i-1));
}*/
tableRow.addView(seatView);
}
tableLayout.addView(tableRow);}
}
}
click here for screenshot

NullPointerException when trying to get information

I am trying to do a basic game.I have classes named Ball.java , Scratch.java and Panel.java
In Panel,I am trying to get information from Ball.java class but I am getting NullPointerException.Where is the mistake in my code?
Getting exceiption in this code in Panel.java
public Rect getBoundsBall(){
return new Rect (top.getX(), top.getY(),top.getX()+ball.getWidth() ,top.getY()+ball.getHeight() );
}
Error Log
10-13 12:57:28.746: E/AndroidRuntime(367): FATAL EXCEPTION: Thread-10
10-13 12:57:28.746: E/AndroidRuntime(367): java.lang.NullPointerException
10-13 12:57:28.746: E/AndroidRuntime(367): at com.emredavarci.denemeler.Panel.getBoundsBall(Panel.java:44)
10-13 12:57:28.746: E/AndroidRuntime(367): at com.emredavarci.denemeler.Panel.update(Panel.java:70)
10-13 12:57:28.746: E/AndroidRuntime(367): at com.emredavarci.denemeler.TutorialThread.run(TutorialThread.java:30)
Panel.java
public class Panel extends SurfaceView implements SurfaceHolder.Callback {
private TutorialThread _thread;
Scratch raket=new Scratch();
Ball top=new Ball();
Bitmap ball;
Bitmap _scratch;
public Panel(Context context) {
super(context);
getHolder().addCallback(this);
_thread = new TutorialThread(getHolder(), this); /
setFocusable(true);
}
#Override
public boolean onTouchEvent(MotionEvent event) { // to
switch (event.getAction()){
case MotionEvent.ACTION_MOVE: //
raket.setX((int)(event.getX()));
break;
}
return true;
}
public Rect getBoundsBall(){
return new Rect (top.getX(), top.getY(),top.getX()+ball.getWidth() ,top.getY()+ball.getHeight() );
}
public Rect getBoundsScratch(){
return new Rect (raket.getX(), raket.getY(),raket.getX()+_scratch.getWidth() ,raket.getY()+_scratch.getHeight() );
}
public void update(){ /
if((top.getX()<480) && (top.getX()>0)){
top.setX(top.getX()+top.getxdirection());
}
if((top.getX()==480) || (top.getX()==0)){
top.setxdirection(-1);
top.setX(top.getX()+top.getxdirection());
}
if((top.getY()<780) && (top.getY()>0)){
top.setY(top.getY()+top.getydirection());
}
if((top.getY()==780) || (top.getY()==0)){
top.setydirection(-1);
top.setY(top.getY()+top.getydirection());
}
Rect BallBounds = getBoundsBall();
Rect ScratchBounds = getBoundsScratch();
if( BallBounds.intersect(ScratchBounds) ){
top.setydirection(-1);
//top.setY(top.getY()); !!!!
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// TODO Auto-generated method stub
}
public void surfaceCreated(SurfaceHolder holder) {
_thread.setRunning(true);
_thread.start();
}
public void surfaceDestroyed(SurfaceHolder holder) {
// simply copied from sample application LunarLander:
// we have to tell thread to shut down & wait for it to finish, or else
// it might touch the Surface after we return and explode
boolean retry = true;
_thread.setRunning(false);
while (retry) {
try {
_thread.join();
retry = false;
} catch (InterruptedException e) {
// we will try it again and again...
}
}
}
#Override
public void onDraw(Canvas canvas) {
_scratch = BitmapFactory.decodeResource(getResources(), R.drawable.red2);
ball = BitmapFactory.decodeResource(getResources(), R.drawable.ball);
canvas.drawColor(Color.BLACK);
canvas.drawBitmap(_scratch, raket.getX() - (_scratch.getWidth() / 2), raket.getY() - (_scratch.getHeight() / 2), null);
canvas.drawBitmap(ball, top.getX() - (ball.getWidth() / 2), top.getY() - (ball.getHeight() / 2), null);
}
}
Ball.java
public class Ball {
private int x=100; // the X coordinate
private int y=100; // the Y coordinate
int xdirection=10;
int ydirection=10;
public Ball() {
// TODO Auto-generated constructor stub
}
public int getX(){
return x;
}
public int getY(){
return y;
}
public void setX(int a){
x=a;
}
public void setY(int b){
y=b;
}
public int getxdirection(){
return xdirection;
}
public int getydirection(){
return ydirection;
}
public void setxdirection(int a){
xdirection=xdirection*a;
}
public void setydirection(int b){
ydirection=ydirection*b;
}
//while ile ball u hareket ettir
//ball un koordinatlarını sakla
}
Scratch.java
public class Scratch {
private int x = 250;
private int y = 600;
public Scratch() {
// TODO Auto-generated constructor stub
}
public void setX(int a){
x=a;
}
public void setY(int b){
y=b;
}
public int getX(){
return x;
}
public int getY(){
return y;
}
}
You are missing something like:
Ball top = new Ball();
i.e. the variable top is not initialized, but used in the update method.
Also, initialize the ball object outsite of onDraw. Who knows if update will be called before onDraw?
Adding to #Rudolph's answer, are you sure Bitmap ball is initialized? To be sure, try logging ball as:
public Rect getBoundsBall(){
log.v("ball",""+ball);
return new Rect (top.getX(), top.getY(),top.getX()+ball.getWidth() ,top.getY()+ball.getHeight() );
}
Either ball or top is the culprit. Find out which one is uninitialized and tackle it accordingly.

How can I change the picture that draws on the screen

This might seem like a silly qustion but how do you change the picture that draws on the screen.I have already been able to program a app were it draws a little icon where you touch the screen.So natually after I completed that I want to make it better by adding a option menu and the ability to change what icon you were being drown but when I ran the code the icon picture stayed the same.When I looked at it I found that when you click on any of the menu item it does do it's job and change the image id but when you go back to the main screen and try to create a new image it revertes back to the old image.I have no idea why it doesn't change because when I look at it everything make sense for it to change icon properly.If any one has any idea on what i am doing wrong or any suggestion on how to do this it would be greatly appreciate
Main
public class main extends Activity {
/** Called when the activity is first created. */
MenuItem item2;
int item3=R.drawable.ic_launcher;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FrameLayout sv = new FrameLayout(this);
LinearLayout ll = new LinearLayout(this);
Panel test = new Panel(this);
//ImageButton button = new ImageButton(this);
ll.setOrientation(LinearLayout.VERTICAL);
sv.addView(test);
//ll.addView(button);
sv.addView(ll);
setContentView(sv);
}
public boolean onCreateOptionsMenu(Menu menu) {
// TODO Auto-generated method stub
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// TODO Auto-generated method stub
Log.v("test", "item3 before is: "+item3);
item3=R.drawable.box;
Log.v("test", "item3 after is: "+item3);
return super.onOptionsItemSelected(item);
}
}
Panel
public class Panel extends SurfaceView implements SurfaceHolder.Callback {
private Bitmap image;
private ViewThread mThread;
private int x;
private int y;
private ArrayList<Element> mElements = new ArrayList<Element>();
public Panel(Context context) {
super(context );
image = BitmapFactory.decodeResource(getResources(),yantz.imageapp4.R.drawable.test);
getHolder().addCallback(this);
mThread = new ViewThread(this);
}
public void doDraw(Canvas canvas) {
canvas.drawColor(Color.CYAN);
canvas.drawBitmap(image, x, y, null);
synchronized (mElements){
for(Element element : mElements){
element.doDraw(canvas);
}
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
Log.v("test", "you have touched the sreen: ");
synchronized (mElements){
mElements.add(new Element(getResources(),(int) event.getX(),(int) event.getY()));
}
return super.onTouchEvent(event);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// TODO Auto-generated method stub
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
if (!mThread.isAlive()) {
mThread = new ViewThread(this);
mThread.setRunning(true);
mThread.start();
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (mThread.isAlive()) {
mThread.setRunning(false);
}
}
}
Elements
public class Element extends main{
private int mX;
private int mY;
int location ;
private Bitmap mBitmap;
public Element(Resources res, int x, int y) {
Log.v("element", "item3 before location is: "+item3);
location =item3;
mBitmap = BitmapFactory.decodeResource(res, location);
mX = x - mBitmap.getWidth() / 2;
mY = y - mBitmap.getHeight() / 2;
Log.v("element", "item3 before location is: "+item3);
}
public void doDraw(Canvas canvas) {
canvas.drawBitmap(mBitmap, mX, mY, null);
}
public void setlocation(int location2){
location=location2;
}
}
ViewThread
public class ViewThread extends Thread {
private Panel mPanel;
private SurfaceHolder mHolder;
private boolean mRun = false;
public ViewThread(Panel panel) {
mPanel = panel;
mHolder = mPanel.getHolder();
}
public void setRunning(boolean run) {
mRun = run;
}
#Override
public void run() {
Canvas canvas = null;
while (mRun) {
canvas = mHolder.lockCanvas();
if (canvas != null) {
mPanel.doDraw(canvas);
mHolder.unlockCanvasAndPost(canvas);
}
}
}
}
you can use
#Override
protected void onResume() {
super.onResume();
id="what ever you want";
//and set it to imagevIew;
}
if i have understood the uestion correctly,this happens because your activity pauses when it is not focused and resumes with default values.

Categories

Resources