2011年11月10日 星期四

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>


沒有留言: