当前位置:  编程技术>移动开发
本页文章导读:
    ▪ADT20与SDK兼容有关问题        ADT20与SDK兼容问题 ADT20与SDK兼容问题 =============================== 问题一:更新ADT20后,创建工程时无法点击Finish。 问题二:刚才更新SDK, ADT,可是新建项目的时候却出现问题了,操作一路.........
    ▪ 容易设置TextView 跑马观花效果        简单设置TextView 跑马观花效果<TextView         android:id="@+id/top_title"         android:layout_width="wrap_content"         android:layout_height="wrap_content"         android:layout_marginLeft="30dp"   .........
    ▪ gallery3d的源码分析-数据涞源二       gallery3d的源码分析-数据涞源2 花开两朵,各表一枝。上回书讲到了数据cache的一些流程。这回书要说的就是gallery3d刚开始在手机上运行cache数据的流程。   如果你切换手机的语言,跟此流程.........

[1]ADT20与SDK兼容有关问题
    来源: 互联网  发布时间: 2014-02-18
ADT20与SDK兼容问题
ADT20与SDK兼容问题 ===============================

问题一:更新ADT20后,创建工程时无法点击Finish。

问题二:刚才更新SDK, ADT,可是新建项目的时候却出现问题了,操作一路默认,出现了下面的提示:
This  template depends on the Android Support library, which is either not installed, or the
template depends on a more recent version than the one you hava installed.
http://developer.android.com/tools/extras/support-library.html
Required version: 8
Installed version: Not installed
You can install or upgrade it by clicking the Install button below, or alternatively, you can
install it outside of Eclipse with the SDK Manager, the click on "Check Again" to proceed.
两个按钮:Install/Upgrade   Check Again
按照提示安装升级了一下,再次Check Again, 还是这个错误提示。

================================

解决办法一:

1.进入安装目录“android-sdk-windows”下,打开“SDK Manager.exe”;(不要在eclipse里打开,这算是一个BUG吧...)

2.找到Extras,选中Android Support Library,Delete package卸载掉当前的Android Support Library;

3.在Eclipse中创建一个新的工程,在最后一步的时候重新安装Android Support Library即可。


解决办法二:

1.关闭 eclipse ,结束 adb.exe 进程
2.进入安装目录“android-sdk-windows”,打开\extras\android,没有support文件夹但是有一个compatibility文件夹,新建support文件夹,将compatibility文件夹里面的文件复制到“support”文件夹;
ps:compatibility文件夹可能不是存在,可以在安装目录看到“android-compatibility”文件夹,将该文件夹里面的文件复制到support里面,效果一样
3.重新启动eclipse,新建项目OK

    
[2] 容易设置TextView 跑马观花效果
    来源: 互联网  发布时间: 2014-02-18
简单设置TextView 跑马观花效果

<TextView
        android:id="@+id/top_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="30dp"
        android:layout_marginRight="30dp"
        android:layout_alignWithParentIfMissing="true"
        android:layout_centerInParent="true"
        android:layout_toLeftOf="@id/top_btn_right"
        android:layout_toRightOf="@id/top_btn_left"
        android:enabled="true"
        android:scrollHorizontally="true"
        android:gravity="center"
        android:focusable="true"
        android:singleLine="true"
        android:ellipsize="marquee"
        android:marqueeRepeatLimit="marquee_forever"
        android:focusableInTouchMode="true"
        android:textColor="#ffffffff"
        android:textSize="24.0sp" />

1.加蓝色部分注意啦都必须加上,不然没效果!原因是其他视图影响后 android:focusable="true"可能获取不到焦点。

2.所以加上android:focusableInTouchMode="true" 解决获取不到焦点,触摸模式获取后及滚动开始。
3.如果还是不能解决效果就只能在代码中获取焦点了,使用textview.requestFocus() 方法获取。


    
[3] gallery3d的源码分析-数据涞源二
    来源: 互联网  发布时间: 2014-02-18
gallery3d的源码分析-数据涞源2
 花开两朵,各表一枝。上回书讲到了数据cache的一些流程。这回书要说的就是gallery3d刚开始在手机上运行cache数据的流程。
 
如果你切换手机的语言,跟此流程一致。这个在上回书也提到了。
 
首先来看看startNewCacheThread函数:
 
private void startNewCacheThread() {
        restartThread(CACHE_THREAD, "CacheRefresh", new Runnable() //开启线程,如果之前有同样的线程已经存在,关闭之前线程
        {
            public void run() {
                refresh(CacheService.this);//cache媒体数据
            }
        });
    }
restartThread函数的源代码如下,不细说。
private static final void restartThread(final AtomicReference<Thread> threadRef, final String name, final Runnable action) {
        // Create a new thread.
        final Thread newThread = new Thread() {
            public void run() {
                try {
                    action.run();
                } finally {
                    threadRef.compareAndSet(this, null);
                }
            }
        };
        newThread.setName(name);
        newThread.start();
        // Interrupt any existing thread.
        final Thread existingThread = threadRef.getAndSet(newThread);
        if (existingThread != null) {
            existingThread.interrupt();
        }
    }
接下来分析关键的refresh函数:
 
 private final static void refresh(final Context context) {
        // First we build the album cache.
        // This is the meta-data about the albums / buckets on the SD card.
        Log.i(TAG, "Refreshing cache.");
        sAlbumCache.deleteAll(); 
        putLocaleForAlbumCache(Locale.getDefault());

        final ArrayList<MediaSet> sets = new ArrayList<MediaSet>();
        LongSparseArray<MediaSet> acceleratedSets = new LongSparseArray<MediaSet>();
        Log.i(TAG, "Building albums.");
        final Uri uriImages = Images.Media.EXTERNAL_CONTENT_URI.buildUpon().appendQueryParameter("distinct", "true").build();
        final Uri uriVideos = Video.Media.EXTERNAL_CONTENT_URI.buildUpon().appendQueryParameter("distinct", "true").build();
        final ContentResolver cr = context.getContentResolver();
        try {
            final Cursor cursorImages = cr.query(uriImages, BUCKET_PROJECTION_IMAGES, null, null, DEFAULT_BUCKET_SORT_ORDER);//搜索图像
            final Cursor cursorVideos = cr.query(uriVideos, BUCKET_PROJECTION_VIDEOS, null, null, DEFAULT_BUCKET_SORT_ORDER);//搜索视频
            Cursor[] cursors = new Cursor[2];
            cursors[0] = cursorImages;
            cursors[1] = cursorVideos;
            final SortCursor sortCursor = new SortCursor(cursors, Images.ImageColumns.BUCKET_DISPLAY_NAME, SortCursor.TYPE_STRING,
                    true);
            try {
                if (sortCursor != null && sortCursor.moveToFirst()) {
                    sets.ensureCapacity(sortCursor.getCount());
                    acceleratedSets = new LongSparseArray<MediaSet>(sortCursor.getCount());
                    MediaSet cameraSet = new MediaSet();
                    cameraSet.mId = LocalDataSource.CAMERA_BUCKET_ID;//相机的bucket id
                    cameraSet.mName = context.getResources().getString(R.string.camera);
                    sets.add(cameraSet);
                    acceleratedSets.put(cameraSet.mId, cameraSet);//将相机的照片集加入acceleratedSets映射表
                    do {
                        if (Thread.interrupted()) {
                            return;
                        }
                        long setId = sortCursor.getLong(BUCKET_ID_INDEX);
                        MediaSet mediaSet = findSet(setId, acceleratedSets);
                        if (mediaSet == null) {//如果在acceleratedSets映射表找不到setId, 那么加入acceleratedSets映射表
                            mediaSet = new MediaSet();
                            mediaSet.mId = setId;
                            mediaSet.mName = sortCursor.getString(BUCKET_NAME_INDEX);
                            sets.add(mediaSet);
                            acceleratedSets.put(setId, mediaSet);
                        }
                        mediaSet.mHasImages |= (sortCursor.getCurrentCursorIndex() == 0);
                        mediaSet.mHasVideos |= (sortCursor.getCurrentCursorIndex() == 1);
                    } while (sortCursor.moveToNext());
                    sortCursor.close();
                }
            } finally {
                if (sortCursor != null)
                    sortCursor.close();
            }

            sAlbumCache.put(ALBUM_CACHE_INCOMPLETE_INDEX, sDummyData, 0);//写入dummy data到ALBUM_CACHE_INCOMPLETE_INDEX块,说明目前cache开始
            writeSetsToCache(sets);//cache媒体集
            Log.i(TAG, "Done building albums.");
            // Now we must cache the items contained in every album / bucket.
            populateMediaItemsForSets(context, sets, acceleratedSets, false);//将media item归类到sets,并将item信息cache
        } catch (Exception e) {
            // If the database operation failed for any reason.
            ;
        }
        sAlbumCache.delete(ALBUM_CACHE_INCOMPLETE_INDEX);//删除ALBUM_CACHE_INCOMPLETE_INDEX块,说明目前cache技术
    }
 
CAMERA_BUCKET_ID的定义是这样的,其实就是相机目录的hash码。
 
public static final int CAMERA_BUCKET_ID = getBucketId(CAMERA_BUCKET_NAME);
 
    public static final String CAMERA_BUCKET_NAME = Environment.getExternalStorageDirectory().toString() + "/DCIM/" + CAMERA_STRING;//相机目录
 
public static int getBucketId(String path) {
        return (path.toLowerCase().hashCode());
    }
 
下面是writeSetsToCache函数的功能,就是cache相册信息:
 
private static final void writeSetsToCache(final ArrayList<MediaSet> sets) {
        final ByteArrayOutputStream bos = new ByteArrayOutputStream();
        final int numSets = sets.size();
        final DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(bos, 256));
        try {
            dos.writeInt(numSets);
            for (int i = 0; i < numSets; ++i) {
                if (Thread.interrupted()) {
                    return;
                }
                final MediaSet set = sets.get(i);
                dos.writeLong(set.mId);//相册id
                Utils.writeUTF(dos, set.mName);//相册名称
                dos.writeBoolean(set.mHasImages);//是否是图片集
                dos.writeBoolean(set.mHasVideos);//是否是视频集
            }
            dos.flush();
            sAlbumCache.put(ALBUM_CACHE_METADATA_INDEX, bos.toByteArray(), 0);//写chunk文件
            dos.close();
            if (numSets == 0) {
                sAlbumCache.deleteAll();
                putLocaleForAlbumCache(Locale.getDefault());
            }
            sAlbumCache.flush();//写index文件
        } catch (IOException e) {
            Log.e(TAG, "Error writing albums to diskcache.");
            sAlbumCache.deleteAll();
            putLocaleForAlbumCache(Locale.getDefault());
        }
    }
关键函数sAlbumCache.put(ALBUM_CACHE_METADATA_INDEX, bos.toByteArray(), 0),我们来看看put函数做了些什么?
 
public void put(long key, byte[] data, long timestamp) {
        // Check to see if the record already exists.
        Record record = null;
        Log.i(TAG, "DiskCache, put key:"+key);
        synchronized (mIndexMap) {
            record = mIndexMap.get(key);
        }
        if (record != null && data.length <= record.sizeOnDisk) {//如果记录在mIndexMap已经存在,替换当前记录
            // We just replace the chunk.
            int currentChunk = record.chunk;
            try {
            	Log.i(TAG, "DiskCache, get chunk file");
                RandomAccessFile chunkFile = getChunkFile(record.chunk);//获取chunk文件
                if (chunkFile != null) {
                    chunkFile.seek(record.offset);
                    chunkFile.write(data);
                    synchronized (mIndexMap) {
                        mIndexMap.put(key, new Record(currentChunk, record.offset, data.length, record.sizeOnDisk, timestamp));//更改mIndexMap的key的记录数据
                    }
                    return;
                }
            } catch (Exception e) {
                Log.e(TAG, "Unable to read from chunk file");
            }
        }
        //如果记录不存在,将新的chunk添加到当前chunk尾部
        // Append a new chunk to the current chunk.
        final int chunk = mTailChunk;
        final RandomAccessFile chunkFile = getChunkFile(chunk);
        if (chunkFile != null) {
            try {
               //将数据写入chunk文件
                final int offset = (int) chunkFile.length();
                chunkFile.seek(offset);
                chunkFile.write(data);
                synchronized (mIndexMap) {
                    mIndexMap.put(key, new Record(chunk, offset, data.length, data.length, timestamp));//将新纪录添加到mIndexMap
                }
                if (offset + data.length > CHUNK_SIZE) {
                    ++mTailChunk;
                }

                if (++mNumInsertions == 64) { // CR: 64 => constant
                    // Flush the index file at a regular interval. To avoid
                    // writing the entire
                    // index each time the format could be changed to an
                    // append-only journal with
                    // a snapshot generated on exit.
                    flush();//写64次后,写索引文件
                }
            } catch (IOException e) {
                Log.e(TAG, "Unable to write new entry to chunk file");
            }
        } else {
            Log.e(TAG, "getChunkFile() returned null");
        }
    }
 
put函数就是把相册集的信息写入chunk文件。
那继续看sAlbumCache.flush()函数:
 
public void flush() {
        if (mNumInsertions != 0) {
            mNumInsertions = 0;
            writeIndex();
        }
    }
 
 
 
    private void writeIndex() {
        final String indexFilePath = getIndexFilePath();
        try {
            // Create a temporary file to write the index into.
            File tempFile = File.createTempFile("DiskCacheIndex", null);//创建临时索引文件
            final FileOutputStream fileOutput = new FileOutputStream(tempFile);
            final BufferedOutputStream bufferedOutput = new BufferedOutputStream(fileOutput, 1024);
            final DataOutputStream dataOutput = new DataOutputStream(bufferedOutput);

            // Write the index header.
            final int numRecords = mIndexMap.size();
            dataOutput.writeInt(INDEX_HEADER_MAGIC);//索引文件头部的关键字
            dataOutput.writeInt(INDEX_HEADER_VERSION);//索引文件头部的关键字
            dataOutput.writeShort(mTailChunk);//尾部chunk索引数
            dataOutput.writeInt(numRecords);//记录条数

            // Write the records.
            //将chunk文件信息写入索引文件
            for (int i = 0; i < numRecords; ++i) {
                final long key = mIndexMap.keyAt(i);
                final Record record = mIndexMap.valueAt(i);
                dataOutput.writeLong(key);
                dataOutput.writeShort(record.chunk);
                dataOutput.writeInt(record.offset);
                dataOutput.writeInt(record.size);
                dataOutput.writeInt(record.sizeOnDisk);
                dataOutput.writeLong(record.timestamp);
            }

            // Close the file.
            dataOutput.close();

            Log.d(TAG, "Wrote index with " + numRecords + " records.");

            // Atomically overwrite the old index file.
            tempFile.renameTo(new File(indexFilePath));//将临时索引文件重命名
        } catch (IOException e) {
            Log.e(TAG, "Unable to write the index file " + indexFilePath);
        }
    }
 
再回到refresh函数,populateMediaItemsForSets做了哪些事情?
 
private final static void populateMediaItemsForSets(final Context context, final ArrayList<MediaSet> sets,
            final LongSparseArray<MediaSet> acceleratedSets, boolean useWhere) {
        if (sets == null || sets.size() == 0 || Thread.interrupted()) {
            return;
        }
        Log.i(TAG, "Building items.");
        final Uri uriImages = Images.Media.EXTERNAL_CONTENT_URI;
        final Uri uriVideos = Video.Media.EXTERNAL_CONTENT_URI;
        final ContentResolver cr = context.getContentResolver();

        String whereClause = null;
        if (useWhere) {
            int numSets = sets.size();
            StringBuffer whereString = new StringBuffer(Images.ImageColumns.BUCKET_ID + " in (");
            for (int i = 0; i < numSets; ++i) {
                whereString.append(sets.get(i).mId);
                if (i != numSets - 1) {
                    whereString.append(",");
                }
            }
            whereString.append(")");
            whereClause = whereString.toString();
            Log.i(TAG, "Updating dirty albums where " + whereClause);
        }
        try {
            final Cursor cursorImages = cr.query(uriImages, PROJECTION_IMAGES, whereClause, null, DEFAULT_IMAGE_SORT_ORDER);
            final Cursor cursorVideos = cr.query(uriVideos, PROJECTION_VIDEOS, whereClause, null, DEFAULT_VIDEO_SORT_ORDER);
            final Cursor[] cursors = new Cursor[2];
            cursors[0] = cursorImages;
            cursors[1] = cursorVideos;
            final SortCursor sortCursor = new SortCursor(cursors, Images.ImageColumns.DATE_TAKEN, SortCursor.TYPE_NUMERIC, true);
            if (Thread.interrupted()) {
                return;
            }
            try {
                if (sortCursor != null && sortCursor.moveToFirst()) {
                    final int count = sortCursor.getCount();
                    final int numSets = sets.size();
                    final int approximateCountPerSet = count / numSets;
                    for (int i = 0; i < numSets; ++i) {
                        final MediaSet set = sets.get(i);
                        set.setNumExpectedItems(approximateCountPerSet);
                    }
                    do {
                        if (Thread.interrupted()) {
                            return;
                        }
                        final MediaItem item = new MediaItem();
                        final boolean isVideo = (sortCursor.getCurrentCursorIndex() == 1);
                        if (isVideo) {
                            populateVideoItemFromCursor(item, cr, sortCursor, CacheService.BASE_CONTENT_STRING_VIDEOS);//获取视频item的信息
                        } else {
                            populateMediaItemFromCursor(item, cr, sortCursor, CacheService.BASE_CONTENT_STRING_IMAGES);//获取图片item的信息
                        }
                        final long setId = sortCursor.getLong(MEDIA_BUCKET_ID_INDEX);
                        final MediaSet set = findSet(setId, acceleratedSets);
                        if (set != null) {
                            set.addItem(item);//将item加入相册集
                        }
                    } while (sortCursor.moveToNext());
                }
            } finally {
                if (sortCursor != null)
                    sortCursor.close();
            }
        } catch (Exception e) {
            // If the database operation failed for any reason
            ;
        }
        if (sets.size() > 0) {
            writeItemsToCache(sets);//缓存sets的item
            Log.i(TAG, "Done building items.");
        }
    }
 
关键函数writeItemsToCache就是缓存每个set的items。
 
private static final void writeItemsToCache(final ArrayList<MediaSet> sets) {
        final int numSets = sets.size();
        for (int i = 0; i < numSets; ++i) {
            if (Thread.interrupted()) {
                return;
            }
            writeItemsForASet(sets.get(i));
        }
        sAlbumCache.flush();
    }

 

 

writeItemsForASet就是将item的信息写入chunk文件,sAlbumCache.flush就是将chunk文件信息写入index文件。
 
private static final void writeItemsForASet(final MediaSet set) {
        final ByteArrayOutputStream bos = new ByteArrayOutputStream();
        final DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(bos, 256));
        try {
            final ArrayList<MediaItem> items = set.getItems();
            final int numItems = items.size();
            dos.writeInt(numItems);
            dos.writeLong(set.mMinTimestamp);
            dos.writeLong(set.mMaxTimestamp);
            for (int i = 0; i < numItems; ++i) {
                MediaItem item = items.get(i);
                if (set.mId == LocalDataSource.CAMERA_BUCKET_ID || set.mId == LocalDataSource.DOWNLOAD_BUCKET_ID) {
                    // Reverse the display order for the camera bucket - want
                    // the latest first.
                    item = items.get(numItems - i - 1);
                }
                dos.writeLong(item.mId);
                Utils.writeUTF(dos, item.mCaption);
                Utils.writeUTF(dos, item.mMimeType);
                dos.writeInt(item.getMediaType());
                dos.writeDouble(item.mLatitude);
                dos.writeDouble(item.mLongitude);
                dos.writeLong(item.mDateTakenInMs);
                dos.writeBoolean(item.mTriedRetrievingExifDateTaken);
                dos.writeLong(item.mDateAddedInSec);
                dos.writeLong(item.mDateModifiedInSec);
                dos.writeInt(item.mDurationInSec);
                dos.writeInt((int) item.mRotation);
                Utils.writeUTF(dos, item.mFilePath);
            }
            dos.flush();
            sAlbumCache.put(set.mId, bos.toByteArray(), 0);
            dos.close();
        } catch (IOException e) {
            Log.e(TAG, "Error writing to diskcache for set " + set.mName);
            sAlbumCache.deleteAll();
            putLocaleForAlbumCache(Locale.getDefault());
        }
    }
 

    
最新技术文章:
▪Android开发之登录验证实例教程
▪Android开发之注册登录方法示例
▪Android获取手机SIM卡运营商信息的方法
▪Android实现将已发送的短信写入短信数据库的...
▪Android发送短信功能代码
▪Android根据电话号码获得联系人头像实例代码
▪Android中GPS定位的用法实例
▪Android实现退出时关闭所有Activity的方法
▪Android实现文件的分割和组装
▪Android录音应用实例教程
▪Android双击返回键退出程序的实现方法
▪Android实现侦听电池状态显示、电量及充电动...
▪Android获取当前已连接的wifi信号强度的方法
▪Android实现动态显示或隐藏密码输入框的内容
▪根据USER-AGENT判断手机类型并跳转到相应的app...
▪Android Touch事件分发过程详解
▪Android中实现为TextView添加多个可点击的文本
▪Android程序设计之AIDL实例详解
▪Android显式启动与隐式启动Activity的区别介绍
▪Android按钮单击事件的四种常用写法总结
▪Android消息处理机制Looper和Handler详解
▪Android实现Back功能代码片段总结
▪Android实用的代码片段 常用代码总结
▪Android实现弹出键盘的方法
▪Android中通过view方式获取当前Activity的屏幕截...
▪Android提高之自定义Menu(TabMenu)实现方法
▪Android提高之多方向抽屉实现方法
▪Android提高之MediaPlayer播放网络音频的实现方法...
▪Android提高之MediaPlayer播放网络视频的实现方法...
▪Android提高之手游转电视游戏的模拟操控
 


站内导航:


特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3