2015年12月28日 星期一

Android 使用xliff 格式化字符串

Copy from http://ezfantasy.iteye.com/blog/1489273

Android 使用xliff 格式化字符串



Android資源字符串/res/values​​/string.xml中可以包含xliff的節點,Xliff是XML Localization Interchange File Format 的縮寫,中文名為XML本地化數據交換格式。

quote from wikipedia ( http://en.wikipedia.org/wiki/XLIFF ) :
"XLIFF  ( XML Localisation Interchange File Format ) is an  XML -based format created to standardize localization . XLIFF was standardized by  OASIS  in 2002. Its current specification is v1.2 [1]  released on Feb-1-2008.
The specification is aimed at the localization industry. It specifies elements and attributes to aid in localization.
XLIFF forms part of the Open Architecture for XML Authoring and Localization ( OAXAL ) reference architecture."

<xliff:g>標籤介紹:
屬性id可以隨便命名
屬性值舉例說明
%n$ms:代表輸出的是字符串,n代表是第幾個參數,設置m的值可以在輸出之前放置空格
%n$ md:代表輸出的是整數,n代表是第幾個參數,設置m的值可以在輸出之前放置空格,也可以設為0m,在輸出之前放置m個0
%n$mf:代表輸出的是浮點數,n代表是第幾個參數,設置m的值可以控制小數位數,如m=2.2時,輸出格式為00.00 

也可簡單寫成:
%d (表示整數)
%f (​​表示浮點數)
%s (表示字符串)

使用步驟舉例:
1.
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
2.
 <string name="test_xliff">小紅今年<xliff:g id="xxx">%d</xliff:g>歲了,上<xliff:g id="yyy">%s</xliff:g >年級!</string>
3. 
String test = String.format(getResources().getString(R.string.test_xliff), 7, "小學二");

輸出:
小紅今年7歲了,上小學二年級!

2015年12月16日 星期三

SQLite in Android

a more easy way to use SQL in Android:

sugar orm
http://satyan.github.io/sugar/index.html


First we need to create a contract

contract is what column should we have in the database, use to define the constant in the database

CREATE TABLE table_name(
   column1 INTEGER AUTOINCREMENT,   must have
   column2 datatype,
   column3 datatype,
   .....
   columnN datatype,
);
Concept:



Example of contract:


/**
 * Defines table and column names for the weather database.
 */
public class WeatherContract {

    // To make it easy to query for the exact date, we normalize all dates that go into
    // the database to the start of the the Julian day at UTC.
    public static long normalizeDate(long startDate) {
        // normalize the start date to the beginning of the (UTC) day
        Time time = new Time();
        time.set(startDate);
        int julianDay = Time.getJulianDay(startDate, time.gmtoff);
        return time.setJulianDay(julianDay);
    }

    /*
        Inner class that defines the table contents of the location table
        Students: This is where you will add the strings.  (Similar to what has been
        done for WeatherEntry)
     */
    public static final class LocationEntry implements BaseColumns {
        public static final String TABLE_NAME = "location";

        //store the seeting of location
        public static final String COLUMN_LOC_SET = "location_set";

        //store the city name, stored as string
        public static final String COLUMN_CITY_NAME = "city_name";

        //store as float
        public static final String COLUMN_COORD_LAT = "coord_lat";
        public static final String COLUMN_COORD_LONG = "coord_long";


    }

    /* Inner class that defines the table contents of the weather table */
    public static final class WeatherEntry implements BaseColumns {

        public static final String TABLE_NAME = "weather";

        // Column with the foreign key into the location table.
        public static final String COLUMN_LOC_KEY = "location_id";
        // Date, stored as long in milliseconds since the epoch
        public static final String COLUMN_DATE = "date";
        // Weather id as returned by API, to identify the icon to be used
        public static final String COLUMN_WEATHER_ID = "weather_id";

        // Short description and long description of the weather, as provided by API.
        // e.g "clear" vs "sky is clear".
        public static final String COLUMN_SHORT_DESC = "short_desc";

        // Min and max temperatures for the day (stored as floats)
        public static final String COLUMN_MIN_TEMP = "min";
        public static final String COLUMN_MAX_TEMP = "max";

        // Humidity is stored as a float representing percentage
        public static final String COLUMN_HUMIDITY = "humidity";

        // Humidity is stored as a float representing percentage
        public static final String COLUMN_PRESSURE = "pressure";

        // Windspeed is stored as a float representing windspeed  mph
        public static final String COLUMN_WIND_SPEED = "wind";

        // Degrees are meteorological degrees (e.g, 0 is north, 180 is south).  Stored as floats.
        public static final String COLUMN_DEGREES = "degrees";
    }
}

Seond,create a SQLiteOpenHelper


Use to help to create and modify the SQLite database

Example:


public class WeatherDbHelper extends SQLiteOpenHelper {

    // If you change the database schema, you must increment the database version.
    private static final int DATABASE_VERSION = 2;

    static final String DATABASE_NAME = "weather.db";

    public WeatherDbHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        final String SQL_CREATE_WEATHER_TABLE = "CREATE TABLE " + WeatherEntry.TABLE_NAME + " (" +
                // Why AutoIncrement here, and not above?
                // Unique keys will be auto-generated in either case.  But for weather
                // forecasting, it's reasonable to assume the user will want information
                // for a certain date and all dates *following*, so the forecast data
                // should be sorted accordingly.
                WeatherEntry._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +

                // the ID of the location entry associated with this weather data
                WeatherEntry.COLUMN_LOC_KEY + " INTEGER NOT NULL, " +
                WeatherEntry.COLUMN_DATE + " INTEGER NOT NULL, " +
                WeatherEntry.COLUMN_SHORT_DESC + " TEXT NOT NULL, " +
                WeatherEntry.COLUMN_WEATHER_ID + " INTEGER NOT NULL," +

                WeatherEntry.COLUMN_MIN_TEMP + " REAL NOT NULL, " +
                WeatherEntry.COLUMN_MAX_TEMP + " REAL NOT NULL, " +

                WeatherEntry.COLUMN_HUMIDITY + " REAL NOT NULL, " +
                WeatherEntry.COLUMN_PRESSURE + " REAL NOT NULL, " +
                WeatherEntry.COLUMN_WIND_SPEED + " REAL NOT NULL, " +
                WeatherEntry.COLUMN_DEGREES + " REAL NOT NULL, " +

                // Set up the location column as a foreign key to location table.
                " FOREIGN KEY (" + WeatherEntry.COLUMN_LOC_KEY + ") REFERENCES " +
                LocationEntry.TABLE_NAME + " (" + LocationEntry._ID + "), " +

                // To assure the application have just one weather entry per day
                // per location, it's created a UNIQUE constraint with REPLACE strategy
                " UNIQUE (" + WeatherEntry.COLUMN_DATE + ", " +
                WeatherEntry.COLUMN_LOC_KEY + ") ON CONFLICT REPLACE);";

        sqLiteDatabase.execSQL(SQL_CREATE_WEATHER_TABLE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
        // This database is only a cache for online data, so its upgrade policy is
        // to simply to discard the data and start over
        // Note that this only fires if you change the version number for your database.
        // It does NOT depend on the version number for your application.
        // If you want to update the schema without wiping data, commenting out the next 2 lines
        // should be your top priority before modifying this method.
        sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + LocationEntry.TABLE_NAME);
        sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + WeatherEntry.TABLE_NAME);
        onCreate(sqLiteDatabase);
    }
}

Thied How to read and query from sql

First ,get reference to writable/readable database:


SQLiteDatabase db = new WeatherDbHelper(

        this.mContext).getWritableDatabase();

Second, create content value of what want to insert:


ContentValues weatherValues = new ContentValues();
weatherValues.put(WeatherContract.WeatherEntry.COLUMN_LOC_KEY, locationRowId);
weatherValues.put(WeatherContract.WeatherEntry.COLUMN_DATE, TEST_DATE);
weatherValues.put(WeatherContract.WeatherEntry.COLUMN_DEGREES, 1.1);
weatherValues.put(WeatherContract.WeatherEntry.COLUMN_HUMIDITY, 1.2);
weatherValues.put(WeatherContract.WeatherEntry.COLUMN_PRESSURE, 1.3);
weatherValues.put(WeatherContract.WeatherEntry.COLUMN_MAX_TEMP, 75);
weatherValues.put(WeatherContract.WeatherEntry.COLUMN_MIN_TEMP, 65);
weatherValues.put(WeatherContract.WeatherEntry.COLUMN_SHORT_DESC, "Asteroids");
weatherValues.put(WeatherContract.WeatherEntry.COLUMN_WIND_SPEED, 5.5);
weatherValues.put(WeatherContract.WeatherEntry.COLUMN_WEATHER_ID, 321);

Third,insert:


ContentValues cv=new ContentValues();
cv.put(WeatherContract.LocationEntry.COLUMN_CITY_NAME,"North Pole");
cv.put(WeatherContract.LocationEntry.COLUMN_COORD_LAT,64.7488);
cv.put(WeatherContract.LocationEntry.COLUMN_COORD_LONG,-147.353);
cv.put(WeatherContract.LocationEntry.COLUMN_LOCATION_SETTING,"99705");


// Insert ContentValues into database and get a row ID back
long r_id = sqlb.insert(WeatherContract.LocationEntry.TABLE_NAME, null, cv);


Fourth,query:





Delete 
Update

Fifth,close the cursor and database:


cursor.close();

db.close();

Optional SQLite Tutorial

copy from:https://www.udacity.com/course/viewer#!/c-ud853/l-3621368730/m-2602608541

Optional SQLite Tutorial

Since Sunshine will be using a SQLite database to store weather data, you should have a basic understanding of SQLite and its commands before continuing this lesson. This is an optional exercise for anyone new to SQL databases or anyone in need of a refresher.

Introduction

SQLite is a relational database management system, which is an implementation of SQL (Structured Query Language). It comes packaged with the Android OS as a C++ library so that apps can have private databases. SQL can be used to create, search and maintain databases. In this tutorial, you will learn about the syntax and usage of SQL and see how to create and manage a small database on your computer. The commands you learn here are similar to the SQL commands you will write for your Sunshine app, in order to store and retrieve weather data from a SQLite database.

Get SQLite

  1. Download the SQLite command line shell and install. You can follow this tutorial or go directly tohttp://sqlite.org/download.html
  2. Open terminal and navigate to a folder of your choice where you will save your database. Create a new database file called sunshine.db and start the SQLite shell (which will recognize your SQL commands) by typing:
    sqlite3 sunshine.db
  3. For a list of all commands:
    .help
  4. One of the commands is to list out all databases. It should display one database called main and the file location on your computer for sunshine.db.
    .databases
    In an app, you can have multiple databases. Our Sunshine app will only have a single database, and that database can contain multiple tables.

Create A Database Table

  1. A table is a collection of rows and columns like a spreadsheet. Use the CREATE TABLE statement to create a new database table called “weather.” Each row will be one day’s worth of weather data. It should have 6 columns of data: ID, date, min temperature, max temperature, humidity, and pressure.
    In the CREATE TABLE statement, each column definition is separated by commas, where you provide the column name and datatype for that column. We also specify that the column should be non-null. We specify the _id column to be the primary key and it’s an integer.
    CREATE TABLE weather( _id INTEGER PRIMARY KEY, date TEXT NOT NULL, min REAL NOT NULL, max REAL NOT NULL, humidity REAL NOT NULL, pressure REAL NOT NULL);
    The list of possible SQLite data types is a useful resource, or you can see this tutorial.
    Note: SQLite keywords, such as CREATE TABLE or PRIMARY KEY, are capitalized for ease of readability to distinguish them from the table and column names that we’ve selected, but you can lowercase the keywords if you want.
    Note: This is not the full table you’ll be using in Sunshine, this is just a simpler version of the table.
  2. Use this command to list out all tables. Ensure that the weather table was created.
    .tables
  3. Use a SELECT statement to return out all rows in the weather table. The * is a symbol that means “all of the columns”. At this time, nothing will be returned because the table is created, but there is no data in the table yet.
    SELECT * FROM weather;
  4. At any point, you can find out the schema of how the tables were created in the database
    .schema

Insert rows

  1. Use an INSERT statement to insert a new row of data into the weather table. The following INSERT statement inserts a row into the weather table for June 25th, 2014, which had a low of 16 degrees, a high of 20 degrees, 0 humidity and 1029 pressure. The _id of this row is 1.
    INSERT INTO weather VALUES(1,'20140625',16,20,0,1029);
  2. Query for all rows in the weather table, and you should see the one row of data you just inserted.
    SELECT * FROM weather;
  3. To have the column name be printed out as well (for easier readability as to what value corresponds to which column), turn the header on. Then do the query again.
    .header on
    SELECT * FROM weather;
  4. Experiment by inserting another 3 rows of data into the weather table.INSERT INTO weather VALUES(2,'20140626',17,21,0,1031);INSERT INTO weather VALUES(3,'20140627',18,22,0,1055);INSERT INTO weather VALUES(4,'20140628',18,21,10,1070);
    Query for all rows to verify they were inserted properly.
    SELECT * FROM weather;

Query rows

  1. Practice doing queries where you provide a selection WHERE clause to narrow down the number of rows that are returned in the result. Always remember the semicolon at the end of a statement!
    For all possible SQLite operators, see this link.
    This query returns rows from the weather table where the date column exactly equals the 20140626.
    SELECT * FROM weather WHERE date == 20140626;
  2. This query returns rows from the weather table where the date column is between 20140625 and 20140628. However, all columns are not returned, we just return the 4 specified columns (_id, date, min, and max) of the rows that match the query.
    SELECT _id,date,min,max FROM weather WHERE date > 20140625 AND date < 20140628;
  3. This query returns rows where the minimum temperature is greater than or equal to 18. Based on those matching rows, we order them based on increasing (also known as ascending or “ASC” for short) max temperature. The first row of the result that is printed out to the command line will be the row (with min temperature >= 18) with max temperature that is lowest out of all rows, so that subsequent rows will have higher max temperature.
    SELECT * FROM weather WHERE min >= 18 ORDER BY max ASC;

Update rows

  1. You can also update existing rows in the database with an UPDATE statement. This statement updates the weather table by setting the minimum temperature to be 0 and maximum temperature to be 100 for rows where the date is greater than 20140626 but less than 20140627.
    UPDATE weather SET min = 0, max = 100 where date >= 20140626 AND date <= 20140627;
    When you print out the whole weather table again, you can see that 2 rows were changed.
    SELECT * FROM weather;

Delete rows

  1. Use a DELETE statement to delete rows from a database table that match the given selection clause. In this case, we delete any rows from the weather table where humidity is not equal to 0.
    DELETE FROM weather WHERE humidity != 0;

Add columns

  1. If you have released a version of your app to users, and then decide you need to change the database schema, such as adding columns, then you’ll need to upgrade your database. You can alter existing tables, by using the ALTER TABLE command.
    Note: In general, you shouldn’t alter a table to remove a column because you’re deleting data and other tables could depend on that column. Instead you can just null out all values in that column.
    This statement alters the weather table by adding another column to the table called description, which will always be non-null and contain text. It will also default to the value ‘Sunny’ if no value is provided. In reality, you would choose a more reasonable default, but this is just for example purposes.
    ALTER TABLE weather ADD COLUMN description TEXT NOT NULL DEFAULT 'Sunny';
    Verify that the new description column exists when you query all rows and all columns.
    SELECT * FROM weather;

Delete table

  1. Delete the weather table by using the DROP TABLE command. Verify there are no more tables in the database.
    DROP TABLE weather;
    .tables
These are just the basics. Feel free to play around with SQLite some more. See this link:http://www.sqlite.org/cli.html
When you’re done, enter .quit to exit, and you can move onto the quiz on the next page!

2015年12月14日 星期一

Android Studio – error Plugin with id ‘com.android.application’ not found - See more at: http://www.desenvolvimentoweb.blog.br/2015/07/android-studio-error-plugin-with-id-com-android-application-not-found/#sthash.VQIYzGZa.dpuf

Put below code in build.gradle file of main Application and sync it.


buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:1.0.0'
    }
}
 
allprojects {
    repositories {
        mavenCentral()
    }
}



Reference

http://stackoverflow.com/questions/24298896/android-studio-error-8-0-plugin-with-id-android-not-found


Picasso 开源项目使用教程

also can use http://frescolib.org/docs/index.html

copy from:http://xiazdong.me/2014/10/03/picasso-tutorial/


Picasso 開源項目使用教程

前言

圖片加載是Android 開發經常要實現的功能,而這也是談到Android 性能優化問題時不得不提的問題,而Picasso 項目就是幫助我們解決這個問題的,而我在網上搜也沒找到比較全面關於Picasso的中文教程,因此這裡就寫一篇關於Picasso 這個開源項目的介紹。

Picasso 基本介紹

  • 項目地址:https://github.com/square/picasso
  • 項目定位:A powerful image downloading and caching library for Android,即實現圖片加載、圖片緩存的功能。
  • 該項目的依賴項目有:okHttp, okHttp-urlConnection, okio。如果通過jar包方式添加則需要注意版本,本文用的版本是:Picasso 2.3.4, okHttp 2.0.0, okHttp-urlConnection 2.0.0, okio 1.0.0;如果通過gradle 添加那麼依賴就自動添加進來了。
  • 很多人會把它和UIL 項目比較,如果你剛剛接觸圖片異步加載,則我比較推薦Picasso,因為使用起來太方便了。

優點

1、入門簡單:一般為了實現一個圖片異步加載的功能,少說必須要使用:AsyncTask, LruCache, DiskCache, BitmapFactory等等,實現起來還是有難度的,但是Picasso只需要一行代碼即可實現圖片異步加載:
Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);
是不是非常方便。
2、自動取消Adapter的下載任務:一般來說我們在實現ListView時會重用view,比如第10個位置的view重用第1個位置的view,當從第1個位置快速滑到第10個位置時,雖然第1個位置的圖片還沒下載好,Picasso能夠幫我們自動取消第1個位置的下載任務,開始第10個位置的下載任務,我們只需要管業務邏輯即可。
3、利用最少的內存對圖片進行變換:簡單的API即可實現圖片的旋轉、改變大小等簡單變換,還能夠自定義變換。
4、自動進行內存和磁盤的緩存 :不需要自己實現緩存(缺點是不能設定緩存大小),當然你在加載圖片時也可以設置成不使用緩存(skipMemoryCache)。
5、提供很好的調試界面:如果開啟調試模式,則如果圖片是從網絡中獲得,則圖片左上角會有紅色三角形;如果圖片從磁盤獲得,則圖片左上角會有黃色三角形;如果圖片從內存獲得,則圖片左上角會有綠色三角形。如圖所示: 
6、支持通過資源id、本地文件、網絡載入圖片 : load()函數即可實現從不同的來源載入圖片。

基本使用方法

一般我遇到的需要實現的功能就是三個:
  • 簡單實現異步加載圖片到ImageView,並在圖片加載成功或失敗時有個回調,即當圖片加載成功時可以自定義一些操作,當圖片加載失敗時可以自定義一些操作。
  • 下載圖片並保存到本地。
  • 對加載的圖片進行變換。
接下去我將會介紹常用的一些函數。

1、加載圖片到ImageView

ImageView  view  =  null ; 
Picasso  picasso  =  Picasso . with ( this ); 
picasso . setIndicatorsEnabled ( true );    //開啟調模式,它能夠在圖片左上角顯示小三角形,這個小三角形的顏色標明了圖片的來源:網絡、內存緩存、磁盤緩存
picasso . setLoggingEnabled ( true );   //打開日誌,即log中會打印出目前下載的進度、情況
picasso . load ( "http://xxx.jpg" )     //可以是本地圖片或網絡圖片
       . placeholder ( R . drawable . placeholder )    //當圖片正在加載時顯示的圖片(optional) 
       . error ( R . drawable . error )            //當圖片加載失敗時顯示的圖片(optional) 
       . into ( view ,  new  Callback ()  {    //將圖片下載完後放進view中,回調是可選的
           @Override 
           public  void  onSuccess ()  { 
               //加載圖片成功時回調
           } 
           @Override 
           public  void  onError ()  { 
               //加載圖片失敗時回調
           } 
       });

2、加載圖片並自定義動作

Target  target  =  new  Target (){ 
      @Override 
      public  void  onBitmapLoaded ( Bitmap  bitmap ,  Picasso . LoadedFrom  loadedFrom )  { 
             //當圖片加載成功時調用,bitmap是加載的圖片,loadFrom標明圖片的來源是網絡、內存還是磁盤
             / /可以在裡面執行把圖片保存到本地的操作
      } 
      @Override 
      public  void  onBitmapFailed ( Drawable  errorDrawable )  {    //當圖片加載失敗時調用
      } 
      @Override 
      public  void  onPrepareLoad ( Drawable  placeHolderDrawable )  {     //當任務被提交時調用
      } 
}; 
picasso . load ( new  File ( "/1.jpg" )). into ( target );  //指定target任務加載圖片

3、對圖片進行變換

Transformation  transformation  =  new  Transformation ()  { 
     @Override 
     public  Bitmap  transform ( Bitmap  bitmap )  { 
        Bitmap  newBitmap  =  null ; 
        //自定義變換
        if ( bitmap  !=  null  &&  ! ​​bitmap . isRecycled ()){    //將舊圖片回收
            bitmap . recycle (); 
        } 
        return  newBitmap ; 
     }

     @Override 
     public  String  key ()  {  //將用作cache的key 
        return  "key" ; 
     } 
}; 
picasso . load ( R . drawable . download ) 
           . skipMemoryCache ()  //不要把加載的圖片放入緩存,也不要從緩存中取圖片
        . transform ( transformation )     //執行自定義變換
        . into ( view );

案例: 實現異步加載圖片的ListView

效果如下:
我們使用到了通用適配器技術(實現代碼為CommonAdapter項目),使得我們的主要代碼只有30+行:
public  class  SimpleListActivity  extends  Activity  {

    @Override 
    protected  void  onCreate ( Bundle  savedInstanceState )  { 
        super . onCreate ( savedInstanceState ); 
        setContentView ( R . layout . activity_simple_list ); 
        List < DataItem >  datas  =  getSampleDatas (); 
        ListView  listView  =  ( ListView ) findViewById ( R . id . list ) ; 
        Picasso . with ( this ). setIndicatorsEnabled ( true ); 
        listView . setAdapter ( new  CommonAdapter < DataItem >( this , datas , R . layout . item_list )  { 
            @Override 
            public  void  convert ( ViewHolder  holder ,  DataItem  item , int  position )  { 
                holder . setText ( R . id . text , item . name ); 
                holder . setImage ( R . id . image , item . url , null );   //setImage函數中使用了Picasso庫
            } 
        }); 
    }

    private  List < DataItem >  getSampleDatas ()  { 
        List < DataItem >  datas  =  new  ArrayList < DataItem >(); 
        String []  urls  =  getResources (). getStringArray ( R . array . urls ); 
        for ( int  i  =  0 ;  i  <  urls . length ;  i ++){ 
            DataItem  item  =  new  DataItem ( urls [ i ], urls [ i ]); 
            datas . add ( item ); 
        } 
        return  datas ; 
    } 
}

class  DataItem { 
    String  url ; 
    String  name ; 
    public  DataItem ( String  url ,  String  name ){ 
        this . url  =  url ; 
        this . name  =  name ; 
    } 
}

參考文獻