1

我已經修改了AOSP「Launcher2」的代碼WallpaperChooser & WallpaperChooserDialogFragment是一個獨立的Gallery應用程序,我希望它可以在API級別7以上API 16上工作。使用Android支持庫的圖庫應用程序的DialogFragments(rev.10)「Compability Package」API API的V4包API 16

使其適用於API級別< 11我添加了Android支持庫(rev.10)「Compability Package」,V4軟件包。

我基於compability包(android.support.v4.app.DialogFragment.java)中對這些建議的更改: DialogFragments with devices api level < 11

否則,該應用程序會崩潰並出現錯誤(「DialogFragment無法附加到容器視圖」)。

但是,應用程序在部署到實際的Jelly Bean 4.1.1設備(Nexus S)時拒絕按預期工作,但它在模擬器上工作得很好。

測試&作品上:

  • Android 2.1的仿真器(API 7)
  • 的Android 2.2模擬器(API 8)
  • 的Android 2.3.3模擬器(API 10)
  • 的Android 4.0.3仿真器(API 15)
  • Android 4.1仿真器(API 16)

  • 的Android 2.3.7設備(API 10)

測試&不工作:

  • 的Android 4.1.1設備(API 16)

在4.1.1設備上運行時,它不會加載/顯示加勒在水平視圖中輕擊它們時的圖像。

選擇並旋轉設備後,它只會顯示每張圖片,然後再次選擇一張新圖片,再次旋轉並正確顯示。

我還沒有設法弄清楚爲什麼它不會在真實的設備上工作,所以任何幫助表示讚賞。 如果我刪除了compability包,並且只針對API級別+11,則該應用在真實的4.1.1設備上運行。

這是應用程序的代碼:

GalleryDemo.java:

package gallery.android.demo; 

import android.support.v4.app.DialogFragment; 
import android.support.v4.app.Fragment; 
import android.support.v4.app.FragmentActivity; 

import android.os.Bundle; 

public class GalleryDemo extends FragmentActivity { 

@Override 
public void onCreate(Bundle icicle) { 
    super.onCreate(icicle); 
    setContentView(R.layout.wallpaper_chooser_base); 

    Fragment fragmentView = getSupportFragmentManager().findFragmentById(R.id.wallpaper_chooser_fragment); 
    if (fragmentView == null) { 
     DialogFragment fragment = GalleryDemoDialogFragment.newInstance(); 
     fragment.show(getSupportFragmentManager(), "dialog"); 
    } 
} 
} 

GalleryDemoDialogFragment。java:

package gallery.android.demo; 

import android.support.v4.app.DialogFragment; 
import android.support.v4.app.FragmentActivity; 

import android.annotation.TargetApi; 
import android.app.Dialog; 
import android.content.DialogInterface; 
import android.content.res.Resources; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.graphics.Canvas; 
import android.graphics.ColorFilter; 
import android.graphics.drawable.Drawable; 
import android.os.AsyncTask; 
import android.os.Build; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.view.ViewGroup; 
import android.widget.AdapterView; 
import android.widget.BaseAdapter; 
import android.widget.Gallery; 
import android.widget.ImageView; 
import android.widget.ListAdapter; 
import android.widget.SpinnerAdapter; 
import android.widget.Toast; 

import java.util.ArrayList; 

@SuppressWarnings("deprecation") 
@TargetApi(16) 
public class GalleryDemoDialogFragment extends DialogFragment implements AdapterView.OnItemSelectedListener, AdapterView.OnItemClickListener { 

private static final String TAG = "GalleryDemoDialogFragment"; 
private static final String EMBEDDED_KEY = "gallery.android.demo.GalleryDemoDialogFragment.EMBEDDED_KEY"; 

private boolean mEmbedded; 
private Bitmap mBitmap = null; 

private ArrayList<Integer> mThumbs; 
private ArrayList<Integer> mImages; 
private WallpaperLoader mLoader; 
private WallpaperDrawable mWallpaperDrawable = new WallpaperDrawable(); 

public static GalleryDemoDialogFragment newInstance() { 
    GalleryDemoDialogFragment fragment = new GalleryDemoDialogFragment(); 
    fragment.setCancelable(true); 
    return fragment; 
} 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    if (savedInstanceState != null && savedInstanceState.containsKey(EMBEDDED_KEY)) { 
     mEmbedded = savedInstanceState.getBoolean(EMBEDDED_KEY); 
    } else { 
     mEmbedded = isInLayout(); 
    } 
} 

@Override 
public void onSaveInstanceState(Bundle outState) { 
    outState.putBoolean(EMBEDDED_KEY, mEmbedded); 
} 

private void cancelLoader() { 
    if (mLoader != null && mLoader.getStatus() != WallpaperLoader.Status.FINISHED) { 
     mLoader.cancel(true); 
     mLoader = null; 
    } 
} 

@Override 
public void onDetach() { 
    super.onDetach(); 
    cancelLoader(); 
} 

@Override 
public void onDestroy() { 
    super.onDestroy(); 
    cancelLoader(); 
} 

@Override 
public void onDismiss(DialogInterface dialog) { 
    super.onDismiss(dialog); 
    FragmentActivity activity = getActivity(); 
    if (activity != null) { 
     activity.finish(); 
    } 
} 

@Override 
public Dialog onCreateDialog(Bundle savedInstanceState) { 
    findWallpapers(); 
    return null; 
} 

@TargetApi(16) 
@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
    findWallpapers(); 
    if (mEmbedded) { 
     View view = inflater.inflate(R.layout.wallpaper_chooser, container, false); 
     switch (Build.VERSION.SDK_INT) { 
     case Build.VERSION_CODES.ICE_CREAM_SANDWICH : 
      view.setBackgroundDrawable(mWallpaperDrawable); 
      break; 
     case Build.VERSION_CODES.JELLY_BEAN : 
      view.setBackground(mWallpaperDrawable); 
      break; 
     default: 
      view.setBackgroundDrawable(mWallpaperDrawable); 
      break; 
     } 

     final Gallery gallery = (Gallery) view.findViewById(R.id.gallery); 
     gallery.setCallbackDuringFling(false); 
     gallery.setOnItemSelectedListener(this); 
     gallery.setAdapter(new ImageAdapter(getActivity())); 

     View setButton = view.findViewById(R.id.set); 
     setButton.setOnClickListener(new OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       int position = gallery.getSelectedItemPosition(); 
       String[] wallpaperArray = getResources().getStringArray(R.array.wallpapers); 
       String name = wallpaperArray[position]+".jpg"; 

       Log.i(TAG, "Position="+position); 
       Log.i(TAG, "Filename="+name); 
       Toast.makeText(getActivity().getApplicationContext(), "(Save2SD)\n"+ 
                     "Position="+position+"\n"+ 
                     "Filename="+name+ 
                     "", Toast.LENGTH_SHORT).show(); 
      } 
     }); 
     return view; 
    } 
    return null; 
} 


@Override 
public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 
} 

@Override 
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { 
    if (mLoader != null && mLoader.getStatus() != WallpaperLoader.Status.FINISHED) { 
     mLoader.cancel(); 
    } 
    Log.d(TAG, "onItemSelected()"); 
    mLoader = (WallpaperLoader) new WallpaperLoader().execute(position); 
} 

@Override 
public void onNothingSelected(AdapterView<?> parent) { 
} 

private void findWallpapers() { 
    mThumbs = new ArrayList<Integer>(24); 
    mImages = new ArrayList<Integer>(24); 

    final Resources resources = getResources(); 
    final String packageName = resources.getResourcePackageName(R.array.wallpapers); 

    addWallpapers(resources, packageName, R.array.wallpapers); 
    addWallpapers(resources, packageName, R.array.extra_wallpapers); 
} 

private void addWallpapers(Resources resources, String packageName, int list) { 
    final String[] extras = resources.getStringArray(list); 
    for (String extra : extras) { 
     int res = resources.getIdentifier(extra, "drawable", packageName); 
     if (res != 0) { 
      final int thumbRes = resources.getIdentifier(extra + "_small", "drawable", packageName); 
      if (thumbRes != 0) { 
       mThumbs.add(thumbRes); 
       mImages.add(res); 
      } 
     } 
    } 
} 


private class ImageAdapter extends BaseAdapter implements ListAdapter, SpinnerAdapter { 
    private LayoutInflater mLayoutInflater; 

    ImageAdapter(FragmentActivity activity) { 
     mLayoutInflater = activity.getLayoutInflater(); 
    } 

    public int getCount() { 
     return mThumbs.size(); 
    } 

    public Object getItem(int position) { 
     return position; 
    } 

    public long getItemId(int position) { 
     return position; 
    } 

    public View getView(int position, View convertView, ViewGroup parent) { 
     View view; 

     if (convertView == null) { 
      view = mLayoutInflater.inflate(R.layout.wallpaper_item, parent, false); 
     } else { 
      view = convertView; 
     } 

     ImageView iv = (ImageView) view.findViewById(R.id.wallpaper_image); 

     int thumbRes = mThumbs.get(position); 
     iv.setImageResource(thumbRes); 

     Drawable thumbDrawable = iv.getDrawable(); 
     if (thumbDrawable != null) { 
      thumbDrawable.setDither(true); 
     } else { 
      Log.e(TAG, "Error decoding thumbnail resId=" + thumbRes + " for wallpaper #" + position); 
     } 
     return view; 
    } 
} 


private class WallpaperLoader extends AsyncTask<Integer, Void, Bitmap> { 
    BitmapFactory.Options mOptions; 

    WallpaperLoader() { 
     mOptions = new BitmapFactory.Options(); 
     mOptions.inDither = false; 
     mOptions.inPreferredConfig = Bitmap.Config.ARGB_8888; 
    } 

    @Override 
    protected Bitmap doInBackground(Integer... params) { 
     if (isCancelled()) return null; 
     try { 
      return BitmapFactory.decodeResource(getResources(), mImages.get(params[0]), mOptions); 
     } catch (OutOfMemoryError e) { 
      return null; 
     } 
    } 

    @Override 
    protected void onPostExecute(Bitmap b) { 
     if (b == null) return; 
     if (!isCancelled() && !mOptions.mCancel) { 
      if (mBitmap != null) { 
       mBitmap.recycle(); 
      } 

      View v = getView(); 
      if (v != null) { 
       Log.d(TAG, "WallpaperLoader.onPostExecute() getView != null"); 
       mBitmap = b; 
       mWallpaperDrawable.setBitmap(b); // Doesn't appear to work on (physical) device with Jelly Bean (4.1.1)? 
       v.postInvalidate(); 
      } else { 
       Log.d(TAG, "WallpaperLoader.onPostExecute(Bitmap b) getView == null"); 
       mBitmap = null; 
       mWallpaperDrawable.setBitmap(null); 
      } 
      mLoader = null; 
     } else { 
      b.recycle(); 
     } 
    } 

    void cancel() { 
     mOptions.requestCancelDecode(); 
     super.cancel(true); 
    } 
} 

private static class WallpaperDrawable extends Drawable { 

    Bitmap mBitmap; 
    int mIntrinsicWidth; 
    int mIntrinsicHeight; 

    void setBitmap(Bitmap bitmap) { 
     Log.d(TAG, "WallpaperDrawable.setBitmap(Bitmap)"); 
     mBitmap = bitmap; 
     if (mBitmap == null) { 
      Log.d(TAG, "WallpaperDrawable.setBitmap(Bitmap) mBitmap == null"); 
      return; 
     } 
     mIntrinsicWidth = mBitmap.getWidth(); 
     mIntrinsicHeight = mBitmap.getHeight(); 
    } 

    @Override 
    public void draw(Canvas canvas) { 
     if (mBitmap == null) { 
      Log.d(TAG, "WallpaperDrawable.draw(Canvas) mBitmap == null"); 
      return; 
     } 
     Log.d(TAG, "WallpaperDrawable.draw(Canvas)"); 
     int width = canvas.getWidth(); 
     int height = canvas.getHeight(); 
     int x = (width - mIntrinsicWidth)/2; 
     int y = (height - mIntrinsicHeight)/2; 
     canvas.drawBitmap(mBitmap, x, y, null); 
    } 

    @Override 
    public int getOpacity() { 
     return android.graphics.PixelFormat.OPAQUE; 
    } 

    @Override 
    public void setAlpha(int alpha) { 
    } 

    @Override 
    public void setColorFilter(ColorFilter cf) { 
    } 
} 
} 
+0

我沒有得到真正的設備上的任何錯誤(JB 4.1.1),它不會使用所選圖像更新視圖。我盡我所能地嘗試調試它,但我只是迷失了方向,想不出別的方法去嘗試。 – kaderud

回答

1

運行API 16的真實設備是硬件加速渲染的唯一設備,這就是爲什麼它的行爲不同。您可以嘗試在您的活動的清單條目中設置android:hardwareAccelerated =「false」以對此進行試驗。

你可以離開加速,如果你調用invalidateSelf()上,當你改變一個可繪製的內容:剛剛

private static class WallpaperDrawable extends Drawable { 
    void setBitmap(Bitmap bitmap) { 
     . . .    
     invalidateSelf(); 
    } 
} 
相關問題