2015年10月29日 星期四

Change the button background

1.at drawable create a xml file.eg custom_button_background.xml

2.define the color in the values/colors.xml

3.in custom_button_background.xml


<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@color/orangeDark" android:state_pressed="true"></item>
    <item android:drawable="@color/orange"></item>

</selector>


android:state_pressed="true" define when press, the color change to this color.

4.Use


<Button
        android:id="@+id/button5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:background="@drawable/custom_button_background"
        android:padding="5dp"
        android:text="@string/materiallize"
        android:textColor="@color/textColor" />


different state:

http://developer.android.com/guide/topics/resources/drawable-resource.html#StateList


2015年10月21日 星期三

Support different size screen

with in a rang, use responisve design,than set a point, use another layout.


to be continued......

SDK - Target and Minimum

SDK is a set of tools that you download that allows you to compile and create Android Projects

minimum SDK is the minimum Android API level that the application is meant to support.

if the SDK  that use by the Android  system is lower than the APP create for, some API will not support.

 target SDK, which is automatically defined for you, signifies the SDK that you use to compile and test with. It should be the most current SDK.

2015年10月19日 星期一

Service-2-On Bind

Another method a Service is Bind Service(都係不會自已整Thread)

The different between the BindService and the normal Service is user can communicate to the  Service after Bind it.

A service can be start and bind at the same time.If a service be bined, if user call stopService() cannot stop it. Until all the user call unvindService();

1.Create a Servie class

public class MyService extends Service {
    


    public MyService() {
    }

   

   

    

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i("ser", "onCreate");
       
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.i("ser", "onDestroy");
       
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("ser", "onStartCommand");
        return super.onStartCommand(intent, flags, startId);

    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        Log.i("ser", "onBind");
        return null;
    }

   
}

2. In the Service call create a innear class MyBinder
MyBinder use to commuincate between the service and the activity.


 class MyBinder extends Binder {
        public MyService getService() {
            return MyService.this;
        }

    }

3.in oerder to communicate to the Service, we need to create some Method,here we create the 
getCurrentNum, it can get the increasing number in the services's worker thread.



public class MyService extends Service {
    MyBinder myBinder;
    private Timer timer;
    private TimerTask timerTask;
    private int i = 0;


    public MyService() {
    }

    private  void startTimer() {
        if (timer == null) {
            timer = new Timer();
            timerTask = new TimerTask() {


                @Override
                public void run() {
                    i++;
                    Log.i("time",i+"");

                }
            };
        }

        timer.schedule(timerTask, 0, 1000);//is a new thread
    }

    private  void stopTimer() {
        if (timer != null) {
            timer.cancel();
            timerTask.cancel();
            timer = null;
        }
    }

    public int getCurrentNum() {

        return i;

    }

4. in the call bindservice Activity, we need to get the MyBind object,so we need the activity exthends ServiceConnection and override onServiceConnected  and onServiceDisconnected


public class MainActivity extends AppCompatActivity implements View.OnClickListener, ServiceConnection {

@Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        Log.i("ser", "onServiceConnected");
        MyService.MyBinder binder = (MyService.MyBinder) service;
       myService=binder.getService();

    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        Log.i("ser", "onServiceDisconnected");

    }


we can see that after we get the MyBind pbject ,than get the service, we can communicate with the service by getCurrentNum.



The hole code

MainActivity


public class MainActivity extends AppCompatActivity implements View.OnClickListener, ServiceConnection {
    MyService myService;
    Intent intent;
    private Button btStart, btStop, btBind, btunBind,btgetBMI;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btStart = (Button) findViewById(R.id.btStartS);
        btStop = (Button) findViewById(R.id.btStopS);
        btBind = (Button) findViewById(R.id.btBinds);
        btunBind = (Button) findViewById(R.id.btUnBind);
        btgetBMI = (Button) findViewById(R.id.btGetBmi);

        btStart.setOnClickListener(this);
        btStop.setOnClickListener(this);
        btBind.setOnClickListener(this);
        btunBind.setOnClickListener(this);
        btgetBMI.setOnClickListener(this);

        intent = new Intent(this, MyService.class);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btStartS:

                startService(intent);
                break;
            case R.id.btStopS:
                stopService(intent);
                break;
            case R.id.btBinds:
                bindService(intent, this, BIND_AUTO_CREATE);
                break;
            case R.id.btUnBind:
                unbindService(this);
                break;
            case R.id.btGetBmi:
               int answer= myService.getCurrentNum();
                Toast.makeText(this,answer+"",Toast.LENGTH_LONG).show();
                break;
        }

    }

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        Log.i("ser", "onServiceConnected");
        MyService.MyBinder binder = (MyService.MyBinder) service;
       myService=binder.getService();

    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        Log.i("ser", "onServiceDisconnected");

    }
}

MyService


public class MyService extends Service {
    MyBinder myBinder;
    private Timer timer;
    private TimerTask timerTask;
    private int i = 0;


    public MyService() {
    }

    private  void startTimer() {
        if (timer == null) {
            timer = new Timer();
            timerTask = new TimerTask() {


                @Override
                public void run() {
                    i++;
                    Log.i("time",i+"");

                }
            };
        }

        timer.schedule(timerTask, 0, 1000);//is a new thread
    }

    private  void stopTimer() {
        if (timer != null) {
            timer.cancel();
            timerTask.cancel();
            timer = null;
        }
    }

    public int getCurrentNum() {

        return i;

    }

    @Override
    protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
        super.dump(fd, writer, args);
        Log.i("ser", "dump");
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i("ser", "onCreate");
        startTimer();
        myBinder = new MyBinder();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.i("ser", "onDestroy");
        stopTimer();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("ser", "onStartCommand");
        return super.onStartCommand(intent, flags, startId);

    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        Log.i("ser", "onBind");
        return myBinder;
    }

    class MyBinder extends Binder {
        public MyService getService() {
            return MyService.this;
        }
    }
}

remark:the timertask will create a worker thraed to calculate

Android color resource

1.create a color.xml file

2.set the color in the xml file

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorBackground">#c213a2</color>
    <color name="colorBackground2">#c213a2</color>
    <color name="colorBackground3">#c213a2</color>
    <color name="colorBackground4">#c213a2</color>
</resources>


3.use in the layout XML code
<
<TextView
        android:id="@+id/tv1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/colorBackground3"
        android:text="Hello World!" />


4. use in the hava program code



TextView tv= (TextView) findViewById(R.id.tv1);

 tv.setBackgroundColor(getResources().getColor(R.color.colorBackground2));


2015年10月18日 星期日

String Resource

In android, the string can as a Resource, define in the xml.
1.define the String, in strings.xml

<resources>
    <string name="app_name">L013String</string>
    <string name="word">Word</string>
</resources>


2.Use in other XML,e.g.,activity_main.xml


<TextView android:text="@string/word" android:layout_width="wrap_content"
        android:layout_height="wrap_content" />


3. Use in the program java code.





 String w=getResources().getString(R.string.word);

Service-1-Start service

服務「啟動」表示應用程式元件 (例如 Activity) 透過呼叫 startService() 來啟動服務。一旦啟動,服務可以無限次數地在背景中執行,就算啟動服務的元件已終結也不會影響。 通常,已啟動的服務會執行單一操作且不會將結果傳回呼叫端。例如,服務可能會透過網路下載或上傳檔案。

服務會在其託管程序的主執行緒中執行 —
 服務不會建立自己的執行緒且不會在另外的程序中執行 (除非您另行指定)。 如果您的服務即將從事任何 CPU 密集的作業或封鎖操作 (如播放 MP3 或連線網路),您應該在服務中建立新的執行緒來執行這些工作。 透過使用另外的執行緒,您會降低應用程式不回應 (ANR) 錯誤的風險,且應用程式的主執行緒仍可以專務於使用者與您的 Activity 互動。

1. Create a Service



public class EchoService extends Service {
    public EchoService() {
    }

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

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }


    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }
}

2.At activity A start A service


Intent intent = new Intent(this,EchoService.class);
  startService(intent);

when you call startService(intent);, will execute onCreate and onStartCommand method. However, will you call again startService, only onStartCommand  will execute again.

when onStartCommand  finish ,the Service object still here

3.Stop the service

In the service :

stopSelf() 

outside the Service:

 stopService()

after call these method, OnDestroy() will call

當不再使用服務且正在終結服務時,系統會呼叫此方法。您的服務應該實作此方法來清除任何如執行緒、註冊的接聽器,接收器等資源。 這會是服務接收到的最後呼叫。


2015年10月15日 星期四

Start another Activity and Get Back the Result

If:
A start B,B give back the information to A

A start B

At A activity

A start B


Intent intent = new Intent(this,actB.class);
startActivityForResult(intent,0);


Reecive the information from B, onActivityResult

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

    }


At B activity

B send back the information and close

Intent i =new Intent();
i.putExtra("name","Roy");
setResult(0,i);
 finish();

2015年10月14日 星期三

制作自定義的View4-使用XML修改 View




package pom.poly.com.trymakeviewbymyself.myView.v4;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;

import pom.poly.com.trymakeviewbymyself.R;
import pom.poly.com.trymakeviewbymyself.myView.v3.BasicView;

/**
 * Created by User on 14/10/2015.
 */
public class NumView extends BasicView {
    private Paint paint = new Paint();
    private String showText = "I love you";
    private int linenum=4;

    public NumView(Context context) {
        super(context);
    }

    public NumView(Context context, AttributeSet attrs) {
        super(context, attrs);
       
    }

    @Override
    protected void drawsub(Canvas canvas) {
        int textSize=100;
        for (int i = 0; i < linenum; i++) {
            textSize = textSize + i*10;
            paint.setTextSize(textSize);
            canvas.drawText(showText, 0, textSize + textSize*i, paint);
        }


    }

    @Override
    protected void logic() {

    }
}

How to no need change the code, use XML to change the number of line that show?
1.create a attrs.xml

in the xmal file

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="NumView">
        <attr name="linenum" format="integer"></attr>
    </declare-styleable>
</resources>

remark:<attr name="linenum" format="integer"></attr>  定義了 linenum e個 attribute 的鄰形是 int

2. use the XML
in the activity_mian.xml
add

xmlns:nv="http://schemas.android.com/apk/res-auto"

than you can use the linenum

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:nv="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <pom.poly.com.trymakeviewbymyself.myView.v4.NumView
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:id="@+id/view"
        android:layout_weight="1"
        nv:linenum="6"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="New Button"
        android:id="@+id/bt1" />
</LinearLayout>

3.change the program that make the program can read the value type in the XML

public NumView(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray ta=context.obtainStyledAttributes(attrs, R.styleable.NumView);
        linenum=ta.getInt(R.styleable.NumView_linenum,0);
        ta.recycle();//release the TypedArray
    }

remark:NumView define in the attrs.xml ,
must need release the TypedArray


制作自定義的View3-提取和封裝自定義View


上次已完成的自定義View


public class LogicView extends View {
    private Paint paint = new Paint();
    private int rx = 0;
    private MyThread myThread = null;
    private String showString = "show me";
    private RectF rectF = new RectF(0, 40, 600, 640);
    private float sweepAngle = 0;

    public LogicView(Context context) {
        super(context);
    }


    public LogicView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        paint.setTextSize(200);
        canvas.drawText(showString, rx, 300, paint);
        canvas.drawArc(rectF, 0, sweepAngle, true, paint);//why true?
        if (myThread == null) {
            myThread = new MyThread();
            myThread.start();
        }
        //invalidate(); //cal by ui thread
        //postInvalidate();
        //canvas.drawText("hi",rx,300,paint);
    }

    class MyThread extends Thread {

        @Override
        public void run() {
            Random random = new Random();
            super.run();

            while (true) {
                if (rx > getWidth()) {
                    rx = 0 - (int) paint.measureText(showString);
                }
                if (sweepAngle > 360) {
                    sweepAngle = 0;
                }

                paint.setARGB(255, random.nextInt(256), random.nextInt(256), random.nextInt(256));//important
                rx = rx + 20;
                sweepAngle += 2;
                postInvalidate();//call by non-UI thread
                try {
                    Thread.sleep(30);//important !!!
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }
    }

}



但要修改和重用會好難,所以要提取和封裝
0.change the name to BaseView
1. 在onDraw中,把


取出,put in to the new Method logic drawsub

void drawsub(Canvas canvas){
        paint.setTextSize(200);
        canvas.drawText(showString, rx, 300, paint);
        canvas.drawArc(rectF, 0, sweepAngle, true, paint);//why true?
    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        drawsub(canvas);
        if (myThread == null) {
            myThread = new MyThread();
            myThread.start();
        }
        //invalidate(); //cal by ui thread
        //postInvalidate();
        //canvas.drawText("hi",rx,300,paint);
    }



2.in the MyThread run() method

pull out


if (rx > getWidth()) {
                    rx = 0 - (int) paint.measureText(showString);
                }
                if (sweepAngle > 360) {
                    sweepAngle = 0;
                }

                paint.setARGB(255, random.nextInt(256), random.nextInt(256), random.nextInt(256));//important
                rx = rx + 20;
                sweepAngle += 2;


put into logic method


void logic(){
    if (rx > getWidth()) {
        rx = 0 - (int) paint.measureText(showString);
    }
    if (sweepAngle > 360) {
        sweepAngle = 0;
    }

    paint.setARGB(255, random.nextInt(256), random.nextInt(256), random.nextInt(256));//important
    rx = rx + 20;
    sweepAngle += 2;
}

public void run() {
            super.run();
            while (running) {
                logic();
                postInvalidate();//call by non-UI thread
                System.out.println("thread still running");
                try {
                    Thread.sleep(30);//important !!!
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }


3. add protected abstract inforant of the logic and drawsub method


 protected abstract void drawsub(Canvas canvas);
 protected abstract void logic();


4.Finally .BaseView


package pom.poly.com.trymakeviewbymyself.myView.v3;

import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.View;

/**
 * Created by User on 14/10/2015.
 */
public abstract class BasicView extends View {

    private MyThread myThread = null;
    private boolean running = true;


    public BasicView(Context context) {
        super(context);
    }

    public BasicView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    protected abstract void drawsub(Canvas canvas);

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (myThread == null) {
            myThread = new MyThread();
            myThread.start();
        } else {
            drawsub(canvas);
        }
        //invalidate(); //cal by ui thread
        //postInvalidate();
        //canvas.drawText("hi",rx,300,paint);
    }

    protected abstract void logic();

    @Override
    protected void onDetachedFromWindow() {
        running=false;
        super.onDetachedFromWindow();
        System.out.println("in onDetachedFromWindow");
    }

    class MyThread extends Thread {

        @Override
        public void run() {
            super.run();
            while (running) {
                logic();
                postInvalidate();//call by non-UI thread
                System.out.println("thread still running");
                try {
                    Thread.sleep(30);//important !!!
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }

    }
}

5. craet LogicView, extends Basae View, overide the logic and drawsub


package pom.poly.com.trymakeviewbymyself.myView.v3;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;

import java.util.Random;

/**
 * Created by User on 14/10/2015.
 */
public class LogicView extends BasicView {
    private Paint paint = new Paint();
    private int rx = 0;
    private Random random = new Random();
    private String showString = "show me";
    private RectF rectF = new RectF(0, 40, 600, 640);
    private float sweepAngle = 0;

    public LogicView(Context context) {
        super(context);
    }

    public LogicView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void drawsub(Canvas canvas) {
        paint.setTextSize(200);
        canvas.drawText(showString, rx, 300, paint);
        canvas.drawArc(rectF, 0, sweepAngle, true, paint);//why true?
    }

    @Override
    protected void logic() {
        if (rx > getWidth()) {
            rx = 0 - (int) paint.measureText(showString);
        }
        if (sweepAngle > 360) {
            sweepAngle = 0;
        }

        paint.setARGB(255, random.nextInt(256), random.nextInt(256), random.nextInt(256));//important
        rx = rx + 20;
        sweepAngle += 2;
    }
}



Now,the view is more easy to change .
The finall important thing is , How to prevent the thread that we create keep run after exit then app?


protected void onDetachedFromWindow() {
        running=false;
        super.onDetachedFromWindow();
        System.out.println("in onDetachedFromWindow");
    }

onDetachedFromWindow call when view detach from the window
at this method,when we seat the boolean to false, the thread stop to loop.