2011年12月18日 星期日
2011年12月6日 星期二
android appwidget使用thread (更新)
Clock_widget.java這個已經我改寫了,這才是我想要寫的thread ,不需要透過Handler,public static void start_service()這靜態方法讓thread直接呼叫來啟動service,
thread中有3個靜態方法set_second(int s) ,stop_thread(),start_thread()讓使用者來設定顯示時間間隔,停止,開始時間,其實我這project已經多加了許多功能(譬如鬧鐘,顯示方
式..),但是還不是我想要的.
滿有趣的我用了一個反向寫程式方法來啟動音樂,在Clock_widget.java結尾的地方(藍色部份)
其他程式部份我會在放上來(待續)
終於知道寫法犯了錯誤,下面的 public void onReceive(Context context, Intent intent)會啟動public Clock_widget()這個建構子,每當我按鈕,onReceive接收,就會呼叫public Clock_widget()這個建構子,因此thread會在產生,一直按就會一直產生thread,解決方法public void onUpdate才是初始化的地方,將public Clock_widget()拿掉,把內容放置onUpdate就OK了.
package test.Clock_widget1;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class CLOCK1_widget1_music_file {
private static File myFilePath;
private static List dirarray;
private static String filepath;
public CLOCK1_widget1_music_file(String path) {
//必須初始化array,否則error
}
//給路徑,取得all file list,給目錄或回上一層使用
public static List get_file_list(String path){
myFilePath = new File(path);
filepath=path;
//必須初始化array,否則error
dirarray=new ArrayList();
//加上第一項
dirarray.add("回到上一層");
//是目錄回傳list
if(myFilePath.isDirectory()){
for(int j=0;j
dirarray.add( myFilePath.list()[j]);
//Log.d("TAG F:",dirarray[j]);
}
}else{
//不是目錄回到上一層
//先回到當前目錄
filepath=myFilePath.getParent();
File f=new File(filepath);
//在一次就是上層目錄,但是若是根目錄除外
if(!filepath.equals("/")){
filepath=f.getParent();
}
myFilePath = new File(filepath );
for(int j=0;j
dirarray.add( myFilePath.list()[j]);
//Log.d("TAG F:",dirarray[j]);
}
}
return dirarray;
}
//當前路徑
public static String get_file_path(){
return filepath;
}
//選中file
public static String get_file(int i){
return dirarray.get(i);
}
public static boolean is_directory(String st){
File myFilePath = new File(st);
return myFilePath.isDirectory();
}
public static boolean is_file(String st){
File myFilePath = new File(st);
return myFilePath.isFile();
}
}
read more...
thread中有3個靜態方法set_second(int s) ,stop_thread(),start_thread()讓使用者來設定顯示時間間隔,停止,開始時間,其實我這project已經多加了許多功能(譬如鬧鐘,顯示方
式..),但是還不是我想要的.
滿有趣的我用了一個反向寫程式方法來啟動音樂,在Clock_widget.java結尾的地方(藍色部份)
其他程式部份我會在放上來(待續)
終於知道寫法犯了錯誤,下面的 public void onReceive(Context context, Intent intent)會啟動public Clock_widget()這個建構子,每當我按鈕,onReceive接收,就會呼叫public Clock_widget()這個建構子,因此thread會在產生,一直按就會一直產生thread,解決方法public void onUpdate才是初始化的地方,將public Clock_widget()拿掉,把內容放置onUpdate就OK了.
package test.Clock_widget1;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class CLOCK1_widget1_music_file {
private static File myFilePath;
private static List
private static String filepath;
public CLOCK1_widget1_music_file(String path) {
//必須初始化array,否則error
}
//給路徑,取得all file list,給目錄或回上一層使用
public static List
myFilePath = new File(path);
filepath=path;
//必須初始化array,否則error
dirarray=new ArrayList
//加上第一項
dirarray.add("回到上一層");
//是目錄回傳list
if(myFilePath.isDirectory()){
for(int j=0;j
dirarray.add( myFilePath.list()[j]);
//Log.d("TAG F:",dirarray[j]);
}
}else{
//不是目錄回到上一層
//先回到當前目錄
filepath=myFilePath.getParent();
File f=new File(filepath);
//在一次就是上層目錄,但是若是根目錄除外
if(!filepath.equals("/")){
filepath=f.getParent();
}
myFilePath = new File(filepath );
for(int j=0;j
dirarray.add( myFilePath.list()[j]);
//Log.d("TAG F:",dirarray[j]);
}
}
return dirarray;
}
//當前路徑
public static String get_file_path(){
return filepath;
}
//選中file
public static String get_file(int i){
return dirarray.get(i);
}
public static boolean is_directory(String st){
File myFilePath = new File(st);
return myFilePath.isDirectory();
}
public static boolean is_file(String st){
File myFilePath = new File(st);
return myFilePath.isFile();
}
}
read more...
2011年12月3日 星期六
TK的canvas元件,清除畫面
畫了3個圓
按清除,被清空畫布
使用set將圓形放入變數中
set cir [$obj create oval $x0 $y0 $x1 $y1 -fill $color -width $line_width ]
就可使用delete來清除了
$obj delete $dc
範例:
#!/usr/bin/wish
#wm deiconify .
#wm title . "test"
#新建窗口
global circle
toplevel .main
wm title .main "Input String Field"
#指定窗口大小(400x400)和位置(60,60)
wm geometry .main 400x400+60+60; update
wm maxsize .main 1028 512
wm minsize .main 128 1
set ::c1 {}
set cx 100
set cy 100
set cr 50
#在窗口開一個frame
frame .main.frame1 -bd 2 -width 400 -height 300 -relief raised
place .main.frame1 -x 0 -y 0
#在frame建立畫布
canvas .main.frame1.canvas
place .main.frame1.canvas -x 0 -y 0
#在frame建立輸入框x
label .main.frame1.lx -text "X:"
place .main.frame1.lx -x 2 -y 270
entry .main.frame1.ex -width 5 -textvariable cx
place .main.frame1.ex -x 20 -y 270
#在frame建立輸入框y
label .main.frame1.ly -text "Y:"
place .main.frame1.ly -x 82 -y 270
entry .main.frame1.ey -width 5 -textvariable cy
place .main.frame1.ey -x 100 -y 270
#在frame建立輸入框r
label .main.frame1.lr -text "R:"
place .main.frame1.lr -x 162 -y 270
entry .main.frame1.er -width 5 -textvariable cr
place .main.frame1.er -x 180 -y 270
tk_optionMenu .main.frame1.to color red blue yellow green
place .main.frame1.to -x 260 -y 270
tk_optionMenu .main.frame1.tol line_width 1 2 3 4 5
place .main.frame1.tol -x 340 -y 270
#按鈕Draw
button .main.a -text "畫圓" -command { draw_circle .main.frame1.canvas $cx $cy $cr $line_width $color }
place .main.a -x 20 -y 360
#按鈕Close
button .main.a1 -text "清除" -command {
delete_circle .main.frame1.canvas $::circle
unset ::circle
#destroy .main
}
place .main.a1 -x 100 -y 360
#按鈕Close
button .main.a2 -text "關閉" -command {
destroy .main
}
place .main.a2 -x 200 -y 360
proc draw_circle {obj x y r line_width color } {
global node
set x0 [ expr $x - $r ]
set y0 [ expr $y - $r ]
set x1 [ expr $x + $r ]
set y1 [ expr $y + $r ]
set cir [$obj create oval $x0 $y0 $x1 $y1 -fill $color -width $line_width ]
lappend ::circle $cir
puts $::circle
}
#將畫布上組件list清除
proc delete_circle {obj list_circle} {
foreach dc $list_circle {
$obj delete $dc
}
}
read more...
按清除,被清空畫布
使用set將圓形放入變數中
set cir [$obj create oval $x0 $y0 $x1 $y1 -fill $color -width $line_width ]
就可使用delete來清除了
$obj delete $dc
範例:
#!/usr/bin/wish
#wm deiconify .
#wm title . "test"
#新建窗口
global circle
toplevel .main
wm title .main "Input String Field"
#指定窗口大小(400x400)和位置(60,60)
wm geometry .main 400x400+60+60; update
wm maxsize .main 1028 512
wm minsize .main 128 1
set ::c1 {}
set cx 100
set cy 100
set cr 50
#在窗口開一個frame
frame .main.frame1 -bd 2 -width 400 -height 300 -relief raised
place .main.frame1 -x 0 -y 0
#在frame建立畫布
canvas .main.frame1.canvas
place .main.frame1.canvas -x 0 -y 0
#在frame建立輸入框x
label .main.frame1.lx -text "X:"
place .main.frame1.lx -x 2 -y 270
entry .main.frame1.ex -width 5 -textvariable cx
place .main.frame1.ex -x 20 -y 270
#在frame建立輸入框y
label .main.frame1.ly -text "Y:"
place .main.frame1.ly -x 82 -y 270
entry .main.frame1.ey -width 5 -textvariable cy
place .main.frame1.ey -x 100 -y 270
#在frame建立輸入框r
label .main.frame1.lr -text "R:"
place .main.frame1.lr -x 162 -y 270
entry .main.frame1.er -width 5 -textvariable cr
place .main.frame1.er -x 180 -y 270
tk_optionMenu .main.frame1.to color red blue yellow green
place .main.frame1.to -x 260 -y 270
tk_optionMenu .main.frame1.tol line_width 1 2 3 4 5
place .main.frame1.tol -x 340 -y 270
#按鈕Draw
button .main.a -text "畫圓" -command { draw_circle .main.frame1.canvas $cx $cy $cr $line_width $color }
place .main.a -x 20 -y 360
#按鈕Close
button .main.a1 -text "清除" -command {
delete_circle .main.frame1.canvas $::circle
unset ::circle
#destroy .main
}
place .main.a1 -x 100 -y 360
#按鈕Close
button .main.a2 -text "關閉" -command {
destroy .main
}
place .main.a2 -x 200 -y 360
proc draw_circle {obj x y r line_width color } {
global node
set x0 [ expr $x - $r ]
set y0 [ expr $y - $r ]
set x1 [ expr $x + $r ]
set y1 [ expr $y + $r ]
set cir [$obj create oval $x0 $y0 $x1 $y1 -fill $color -width $line_width ]
lappend ::circle $cir
puts $::circle
}
#將畫布上組件list清除
proc delete_circle {obj list_circle} {
foreach dc $list_circle {
$obj delete $dc
}
}
read more...
2011年11月25日 星期五
2011年11月19日 星期六
2011年11月11日 星期五
ANDROID DEBUG
程式中加入我們要顯示的字串或整數
字串
Log.d("TAG","true") ;
整數Log.i("TAG",299)
read more...
2011年11月10日 星期四
Laker使用TCL設計一個介面,跑calibre,自動stream gds,跑drc,跑完自動開啟rve
原理:
1.當使用sed要取代gds path,記得將/改成\/,譬如/HOME/USER要用sed改成\/HOME\/USER
2.先使用lakerCalibreRVE開啟rve,然後使用ps aux,用sed配合awk,抓出程序id,然後用kill -9來殺掉rve,目的只是要讓rve連到layout viewer,否則不能link(kill
時要判斷,取得程序id在kill,否則error)
3.當calibre已在跑,那我要如何才知道何時該打開rve(calibre -rve -drc drc_gds_file),若是直接下calibre -rve -drc drc_gds_file一定是打不開,使用bash sell的while迴圈,然後-r判斷檔是否可讀,若是break中斷迴圈,打開rve,最好在配合awk取得file size
while [ 0 -lt 1 ]
do
if [ -r $file ]; then
break
fi
done
取得file size
a=`ls -l CDS.log|gawk '{ print $5 }'`
while [ 0 -lt 1 ]
do
if [ $a -gt 0 ]; then
break
fi
done
在
calibre -rve -drc drc_gds_file
read more...
1.當使用sed要取代gds path,記得將/改成\/,譬如/HOME/USER要用sed改成\/HOME\/USER
2.先使用lakerCalibreRVE開啟rve,然後使用ps aux,用sed配合awk,抓出程序id,然後用kill -9來殺掉rve,目的只是要讓rve連到layout viewer,否則不能link(kill
時要判斷,取得程序id在kill,否則error)
3.當calibre已在跑,那我要如何才知道何時該打開rve(calibre -rve -drc drc_gds_file),若是直接下calibre -rve -drc drc_gds_file一定是打不開,使用bash sell的while迴圈,然後-r判斷檔是否可讀,若是break中斷迴圈,打開rve,最好在配合awk取得file size
while [ 0 -lt 1 ]
do
if [ -r $file ]; then
break
fi
done
取得file size
a=`ls -l CDS.log|gawk '{ print $5 }'`
while [ 0 -lt 1 ]
do
if [ $a -gt 0 ]; then
break
fi
done
在
calibre -rve -drc drc_gds_file
read more...
Android透過activity來設定appwidget

滑鼠點擊時間,跳到設定畫面
點擊按鈕,時間變綠色

重點XML,不要設CONFIGURE(這裡是要使用者點擊appwidget來設定),xml設錯,不是桌面加不上appwidget,不然就是程式繞半天繞不出來,試很久才試出我想要的
AndroidManifest.xml中指定activity既可(如下)
<activity android:name=".clockConfigure"/>
再來建立Intent指定activity,然後綁定textview,重點就這樣
1.Clock_widget.java,注意紅色部份getActivity,setOnClickPendingIntent來綁定
package test.Clock_widget1;
import java.util.Calendar;
import android.app.PendingIntent;
import android.app.Service;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;
import android.widget.RemoteViews;
import android.widget.Toast;
//自定義clock_thread class 繼承Thread,s毫秒送出sendMessage
class clock_Thread extends Thread{
//變數宣告
Handler thandler;
private int sc;
private Message m;
boolean paused;
//建構子,初始化
public clock_Thread(Handler h,int s){
sc=s;//毫秒
thandler =h;
}
public void run(){
super.run();
try{
while(true){
Thread.sleep(sc);
m=new Message();
thandler.sendMessage(m);
}//while
}catch (Exception e) {
Log.d("tag", "error");
// handle exception
}//cttch
}//run
//set handler_
public void set_handler(Handler h){
this.thandler=h;
}
//set second
public void set_second(int s){
this.sc=s;
}
}//thread
public class Clock_widget extends AppWidgetProvider {
//變數宣告
//public Handler c_Handler;
public static Handler w_handler;
private static int[] sappWidgetIds;
private static AppWidgetManager sappWidgetManager;
private static Context scontext;
private clock_Thread cthread;
public static String CLICK_ACTION1 ;
public static String CLICK_ACTION2 ;
public static String CLICK_ACTION3 ;
static private boolean START_TIME;//是否顯示時間
private static final int SHOW_EDITOR = 0;
public static String ACTION_WIDGET_CONFIGURE = "ConfigureWidget";
private PendingIntent refreshPendingIntent;
// 建構子初始化Clock_widget,能初始化盡量初始化
public Clock_widget() {
//按鈕1字串
CLICK_ACTION1 = "test.widget_clock.CLICK1";
//按鈕2字串
CLICK_ACTION2 = "test.widget_clock.CLICK2";
//按鈕2字串
CLICK_ACTION3 = "test.widget_clock.CLICK3";
START_TIME=true;
w_handler=null;
//一開始handler null,1秒送出message
cthread=new clock_Thread(w_handler,1000);
//start thread
cthread.start();
}
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
final String action = intent.getAction();
if(action.equals(CLICK_ACTION1)){
//context.startService(intent1);
START_TIME=true;
Toast.makeText(context, "開時時間", Toast.LENGTH_LONG).show();
}
if(action.equals(CLICK_ACTION2)){
START_TIME=false;
Toast.makeText(context, "停止時間", Toast.LENGTH_LONG).show();
}
}
@Override
public void onUpdate(final Context context,AppWidgetManager appWidgetManager, int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
//onUpdate時放到全域變數
sappWidgetManager = appWidgetManager;
sappWidgetIds = appWidgetIds;
scontext = context;
//設定button1狀態
this.self_update_views(scontext,sappWidgetManager,sappWidgetIds,Clock_widget.CLICK_ACTION1,R.layout.main,R.id.button1,Clock_widget.class,false);
//設定button2狀態
this.self_update_views(scontext,sappWidgetManager,sappWidgetIds,Clock_widget.CLICK_ACTION2,R.layout.main,R.id.button2,Clock_widget.class,false);
//設定textview狀態
this.self_update_views(scontext,sappWidgetManager,sappWidgetIds,"ACTION_WIDGET_CONFIGURE",R.layout.main,R.id.textView1,clockConfigure.class,true);
//new handler,啟動service
w_handler =new Handler(){
public void handleMessage(Message msg) {
Intent intent = new Intent(scontext, MyService.class);
//start service
scontext.startService(intent);
}
};//Hamdler
//重設handler
cthread.set_handler(w_handler);
}//onupdate
//因為太多updateAppWidget,寫成method來處理,xid是xml的id,lid是layout中id(ex:button),as是ACTION STRING
private void self_update_views(final Context ct,AppWidgetManager aw, int[] aids,String as,int xid,int lid,Class ac,boolean at){
final Intent refreshIntent = new Intent(ct, ac);
//set action字串
RemoteViews updateViews = new RemoteViews( ct.getPackageName(), xid);
refreshIntent.setAction(as);
if(at){
//因為要切換到Activity,PendingIntent呼叫getActivity,這裡是重點!!
refreshPendingIntent = PendingIntent.getActivity(ct, 0,refreshIntent, PendingIntent.FLAG_UPDATE_CURRENT);
}else{
// 因為要Broadcast廣播,PendingIntent呼叫getBroadcast
refreshPendingIntent = PendingIntent.getBroadcast(ct, 0,refreshIntent, PendingIntent.FLAG_UPDATE_CURRENT);
}
//final PendingIntent refreshPendingIntent = PendingIntent.getService(cc, 0,refreshIntent, 0);
//設定button當使用者點擊button,然後onReceive接收作判斷,或綁定textview1,當使用者點擊textview啟動activity來改變appwidget
updateViews.setOnClickPendingIntent(lid, refreshPendingIntent);
//update view
aw.updateAppWidget(aids, updateViews);
}
//取得時間,宣告成static可值接用,不須new
public static String get_date(){
int c_Minutes; //分
int c_Hour; //時
int c_Second;
int c_year; //時
int c_month;
final String str;
long time=System.currentTimeMillis();
final Calendar c_Calendar = Calendar.getInstance();
c_Calendar.setTimeInMillis(time);
c_Hour=c_Calendar.get(Calendar.HOUR);
c_Minutes=c_Calendar.get(Calendar.MINUTE);
c_Second=c_Calendar.get(Calendar.SECOND);
c_month=c_Calendar.get(Calendar.MONTH);
c_year=c_Calendar.get(Calendar.YEAR);
str="西元"+c_year+"年"+c_month+"月"+c_Hour+"時"+c_Minutes+"分"+c_Second+"秒";
return str;
}
//MyService服務程式 ,背景運作
public static class MyService extends Service {
//onStart階段service啓動只執行一次
@Override
public void onStart(Intent intent, int startId) {
if(START_TIME){
ComponentName thisWidget = new ComponentName(this, Clock_widget.class);
AppWidgetManager manager = AppWidgetManager.getInstance(this);
RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.main);
//Toast.makeText(this, "開時時間", Toast.LENGTH_LONG).show();
//remoteViews.setTextColor(R.id.textView1, -1);
remoteViews.setTextViewText(R.id.textView1, get_date());
manager.updateAppWidget(thisWidget, remoteViews);
//Log.d("TAG","true") ;
}else{
//Log.d("TAG","false") ;
}//if
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
} //service
}//app class
2.clockConfigure.java,這裡activity只是作text顏色變換沒甚重點,要注意是clockConfigure.this.finish();讓activity還回appwidget
package test.Clock_widget1;
import android.app.Activity;
import android.appwidget.AppWidgetManager;
import android.content.ComponentName;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.widget.RemoteViews;
/**
* @author yplin66
*
*/
/**
* @author yplin66
*
*/
public class clockConfigure extends Activity {
public static String ACTION_WIDGET_CONFIGURE = "ConfigureWidget";
private int mAppWidgetId;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.conf);
}
//botton
public void set_ok(View cv) {
//RemoteViews views = new RemoteViews(clockConfigure.this, R.layout.main);
RemoteViews views = new RemoteViews(getPackageName(), R.layout.main);
ComponentName widget = new ComponentName(clockConfigure.this,Clock_widget.class);
//Updates AppWidget state; gets information about
//installed AppWidget providers and other AppWidget related state.
AppWidgetManager manager = AppWidgetManager.getInstance(clockConfigure.this);
views.setTextColor(R.id.textView1, Color.GREEN);
manager.updateAppWidget(widget, views);
clockConfigure.this.finish();
}//start_clock
}
3.AndroidManifest.xml多一行<activity android:name=".clockConfigure"/>不需要( <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>)
如下
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="test.Clock_widget1"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="11" />
<application android:icon="@drawable/icon" android:label="@string/app_name">
<receiver android:name=".Clock_widget" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<!--receiver註冊action-->
<action android:name="test.widget_clock.CLICK1" />
<action android:name="test.widget_clock.CLICK2" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/clockprovider" />
</receiver>
<service android:enabled="true" android:name=".Clock_widget$MyService">
<intent-filter>
<!--service註冊action,mark掉>
<action android:name="test.widget_clock.CLICK3" />
</-->
</intent-filter>
</service>
<activity android:name=".clockConfigure"/>
</application>
</manifest>
4.clockprovider.xml(appwidget設定檔xml,並指定initialLayout)
也不需註明conigure來源(android:configure="test.widget_clock.colockConfigure")
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider
xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="100dp"
android:minHeight="50dp"
android:updatePeriodMillis="0"
android:initialLayout="@layout/main"
>
</appwidget-provider>
5.conf.xml 設定appwidget的activity的LAYOUT(xml)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="set_ok" android:text="設定綠色"/>
</LinearLayout>
6.main.xml主要viewer(讓appwidget來顯示)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/textView1"
android:layout_width="843dp"
android:layout_height="wrap_content"
android:text="TextView"
android:textSize="18dp" >
</TextView>
<LinearLayout android:id="@+id/linearLayout1" android:layout_height="wrap_content" android:layout_width="match_parent" android:layout_weight="0.13" android:weightSum="1">
<LinearLayout
android:id="@+id/linearLayout2"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<Button android:id="@+id/button1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="顯示時間"></Button>
<Button android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="暫停時間"></Button>
</LinearLayout>
</LinearLayout>
</LinearLayout>
read more...
2011年11月1日 星期二
Android的thread與handler
想好幾天,想不出個所以然,今天總算試出來了
看下面程式,一直會認為當run_clock=true,Log會顯示true,當我設run_clock=false,Log應該顯示出false才對,結果Log是true,false 交互出現,在設一次run_clock=false變成true false false百思不解,亂try一通還真try出來了
class clock_Thread extends Thread{
public void run(){
super.run();
try{
do{
Thread.sleep(1000);
Message m=new Message();
if(run_clock){
w_handler.sendMessage(m);
Log.d("tag", "true");
}else{
w_handler.removeCallbacks(this);
Log.d("tag", "false");
}
}while(true);
}catch (Exception e) {
Log.d("tag", "error");
// TODO: handle exception
}//cttch
}//run
}//thread
正確程式碼如下,當設run_clock=false在else應多寫w_handler.removeCallbacks(this),這樣才是正確讓Handler不送出message
class clock_Thread extends Thread{
public void run(){
super.run();
try{
do{
Thread.sleep(1000);
Message m=new Message();
if(run_clock){
w_handler.sendMessage(m);
Log.d("tag", "true");
}else{
w_handler.removeCallbacks(this);
Log.d("tag", "false");
}
}while(true);
}catch (Exception e) {
Log.d("tag", "error");
// TODO: handle exception
}//cttch
}//run
}//thread
還是不對,上面是出現error而產生的thread異常終止,不是我想要的,似乎是app widget不能讓thread改變,若是把thread在Activity則正常工作,看下面程式,當對clock_Thread使用set_start(false)是可讓時間停止,set_start(true)是可讓時間再次顯示的
package test.clock1;
import java.util.Calendar;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
public class Clock1Activity extends Activity {
private TextView mTextView;
public Calendar c_Calendar; //日曆
public int c_Minutes; //分
public int c_Hour; //時
public int c_Second; //秒
private boolean run_clock;
public Handler c_Handler;
private clock_Thread c_Thread;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mTextView=(TextView)findViewById(R.id.textView1);
mTextView.setTextSize(30);
//hander指派工作
c_Handler =new Handler(){
public void handleMessage(Message msg){
long time=System.currentTimeMillis();
final Calendar c_Calendar = Calendar.getInstance();
c_Calendar.setTimeInMillis(time);
c_Hour=c_Calendar.get(Calendar.HOUR);
c_Minutes=c_Calendar.get(Calendar.MINUTE);
c_Second=c_Calendar.get(Calendar.SECOND);
mTextView.setText(c_Hour+":"+c_Minutes+":"+c_Second);
}
};
//run_clock=true;
run_clock=false;
//產執行續物件
c_Thread = new clock_Thread();
//啟動執行續
c_Thread.start();
}
//button事件,啟動時間
public void clock_start(View cv) {
c_Thread.set_start(true);
}//start_clock
//button事件,停止時間
public void clock_stop(View cv) {
c_Thread.set_start(false);
}//stop_clock
//執行續
class clock_Thread extends Thread{
boolean START=true;
public void run(){
super.run();
try{
do{
Thread.sleep(1000);
if(START){
Message m=new Message();
// 將Message物件送入MessageQueue裡
Log.d("TAG", "OK");
c_Handler.sendMessage(m);
}else{
Log.d("TAG", "NO");
}
}while(true);
}catch (Exception e) {
// TODO: handle exception
}//cttch
}//run
public void set_start(boolean b){
this.START=b;
}
}//thread
}
還是不對,上面是出現error而產生的thread異常終止,不是我想要的,似乎是app widget不能讓thread改變,若是把thread在Activity則正常工作,看下面程式,當對clock_Thread使用set_start(false)是可讓時間停止,set_start(true)是可讓時間再次顯示的
package test.clock1;
import java.util.Calendar;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
public class Clock1Activity extends Activity {
private TextView mTextView;
public Calendar c_Calendar; //日曆
public int c_Minutes; //分
public int c_Hour; //時
public int c_Second; //秒
private boolean run_clock;
public Handler c_Handler;
private clock_Thread c_Thread;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mTextView=(TextView)findViewById(R.id.textView1);
mTextView.setTextSize(30);
//hander指派工作
c_Handler =new Handler(){
public void handleMessage(Message msg){
long time=System.currentTimeMillis();
final Calendar c_Calendar = Calendar.getInstance();
c_Calendar.setTimeInMillis(time);
c_Hour=c_Calendar.get(Calendar.HOUR);
c_Minutes=c_Calendar.get(Calendar.MINUTE);
c_Second=c_Calendar.get(Calendar.SECOND);
mTextView.setText(c_Hour+":"+c_Minutes+":"+c_Second);
}
};
//run_clock=true;
run_clock=false;
//產執行續物件
c_Thread = new clock_Thread();
//啟動執行續
c_Thread.start();
}
//button事件,啟動時間
public void clock_start(View cv) {
c_Thread.set_start(true);
}//start_clock
//button事件,停止時間
public void clock_stop(View cv) {
c_Thread.set_start(false);
}//stop_clock
//執行續
class clock_Thread extends Thread{
boolean START=true;
public void run(){
super.run();
try{
do{
Thread.sleep(1000);
if(START){
Message m=new Message();
// 將Message物件送入MessageQueue裡
Log.d("TAG", "OK");
c_Handler.sendMessage(m);
}else{
Log.d("TAG", "NO");
}
}while(true);
}catch (Exception e) {
// TODO: handle exception
}//cttch
}//run
public void set_start(boolean b){
this.START=b;
}
}//thread
}
read more...
訂閱:
文章 (Atom)