2013年6月23日 星期日

Service BroadcastReceiver Notification 整合應用--在通知列上顯示時間,並常駐!!!

小小的研究心得~分享給大家!!!
程式在按開始後會顯示目前時間及一個計數值,並顯示在通知列上,且通知列上的時間
會持續更新
(顯示計數值是為了確定程式有持續在背景運行)
當使用者按裝置上的Home鍵,程式仍會在背景運行,可點擊通知列上的圖示返回程式
程式畫面:
 

程式流程:
MainActivity ==> 執行 Service (要執行的動作/運算)
Service ==> 運用 BroadcastReceiver 改變主畫面 UI / 生成 Notification
AndroidManifest.xml 要記得加上 service

程式碼:
=============layout=============

    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

   
        android:id="@+id/btn_start"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="39dp"
        android:layout_marginTop="28dp"
        android:text="開始" />

   
        android:id="@+id/btn_stop"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/btn_start"
        android:layout_alignBottom="@+id/btn_start"
        android:layout_centerHorizontal="true"
        android:text="結束" />

   
        android:id="@+id/tv_timer"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/btn_start"
        android:layout_marginTop="19dp"
        android:text="Medium Text"
        android:textAppearance="?android:attr/textAppearanceMedium" />

   
        android:id="@+id/tv_counter"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/tv_timer"
        android:layout_below="@+id/tv_timer"
        android:layout_marginTop="19dp"
        android:text="Medium Text"
        android:textAppearance="?android:attr/textAppearanceMedium" />



=============MainActivity.java=============
package com.example.testservice003;

import android.os.Bundle;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v4.app.NotificationCompat;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity implements OnClickListener{
Button start,stop;
TextView show,counter;
static final String ActionFlag = "showtime"; //自訂動作
NotificationManager NM;
Context mContext;
myReceiver mr;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

start = (Button)this.findViewById(R.id.btn_start);
stop = (Button)this.findViewById(R.id.btn_stop);
show = (TextView)this.findViewById(R.id.tv_timer);
counter = (TextView)this.findViewById(R.id.tv_counter);
mContext = this;

//取得NotificationManager
NM = (NotificationManager)this.getSystemService(Context.NOTIFICATION_SERVICE);
//生成 BroadcastReceiver instance
mr = new myReceiver();
//設定自定動作給 Receiver 用
IntentFilter intentFilter = new IntentFilter(ActionFlag);
registerReceiver(mr, intentFilter);

start.setOnClickListener(this);
stop.setOnClickListener(this);
}

@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mr); //在Activity 消滅時才unregister
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

@Override
public void onClick(View v) {
Intent intent = new Intent(getBaseContext(), myService.class);
Bundle bundle = new Bundle();
switch (v.getId()) {
case R.id.btn_start:
//將動作傳給預備回傳資料的 Service
bundle.putString("action", ActionFlag);
intent.putExtras(bundle);
startService(intent);
break;
case R.id.btn_stop:
//將動作傳給預備回傳資料的 Service
bundle.putString("action", ActionFlag);
intent.putExtras(bundle);
stopService(intent);
break;
}
}

class myReceiver extends BroadcastReceiver{

@Override
public void onReceive(Context context, Intent intent) {
//判斷是否為自訂動作 showtime
if(intent.getAction()==ActionFlag){
//將傳回值塞入View 及 變數中
Bundle bundle = intent.getExtras();
show.setText(bundle.getString("time"));
counter.setText(bundle.getInt("counter")+"");
//取得預備要執行的動作
String action = bundle.getString("action");

if(action.equals("start")){
//準備返回用的Intent
Intent backToMain = new Intent(mContext,MainActivity.class);
//Bundle comebackbundle = new Bundle();
//comebackbundle.putString("comback", "我回來主程式了"); 這個要API Level16 才能用
//PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, backToMain, 0, comebackbundle);
PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, backToMain, 0);

Notification NF = new NotificationCompat.Builder(mContext)
.setContentTitle("顯示時間") //設定Notification 抬頭
.setContentText(bundle.getString("time")) //設定Notification 顯示內容
.setContentInfo("info訊息") //設定Notification 右方訊息
.setTicker("有時間顯示囉!!") //設定Notification 一開始顯示文字
.setSmallIcon(R.drawable.ic_launcher) //設定Notification 的Icon
.setContentIntent(pendingIntent) //設定Notification 點擊返回的Activity
.setAutoCancel(false) //設定Notification 是否點擊後就消除
.build();
         //設定Notification不被清除

          NF.flags = Notification.FLAG_NO_CLEAR;
//生成Notification 並給定識別號碼 1
NM.notify(1,NF);
}else{
//取消Notificaiton
NM.cancel(1);
}
}
}
}
}

=============myService.java=============
package com.example.testservice003;

import java.util.Date;

import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;

public class myService extends Service {
Handler handler = new Handler();
String action ="";
int counter;

@Override
public IBinder onBind(Intent intent) {
return null;
}

@Override
public void onCreate() {

super.onCreate();
}

@Override
public void onDestroy() {
//移除Runnable
handler.removeCallbacks(timer);

//準備傳回資料到Receiver,準備關閉Notification
Intent intent = new Intent(action);
Bundle bundle = new Bundle();
bundle.putString("action", "stop");
intent.putExtras(bundle);
sendBroadcast(intent);

super.onDestroy();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//取得動作
action = intent.getExtras().getString("action");
//每隔一秒執行 timer 的動作
handler.postDelayed(timer, 1000);
return START_NOT_STICKY;
}

Runnable timer = new Runnable() {
@Override
public void run() {
counter++;
sendToReceiver(new Date().toString(), counter);
//每隔一秒重覆執行
handler.postDelayed(this, 1000);
}
};

private void sendToReceiver(String time,int number){
//預備將資料傳回給Receiver,由其來做UI的改變
Intent intent = new Intent(action);
Bundle bundle = new Bundle();
bundle.putString("time", time);
bundle.putInt("counter", number);
bundle.putString("action", "start");
intent.putExtras(bundle);
sendBroadcast(intent);
}
}
           
               
           
       
       
   

2013年6月20日 星期四

鐵馬族的好幫手 --> 樂活鐵馬 v1.10 已於 google play 上架


樂活鐵馬 v1.10
提供:
即時定位
(提供時間/速度/距離/方位/精確度等訊息)
路徑紀錄
(背景運作將行經路徑資料寫進資料庫)
歷史紀錄查詢
(提供查詢時間所記錄的路徑騎乘資訊)
鄰近商家提示
(地址/聯絡方式/路徑規劃)
提供帳號登入功能
(可供多人使用同一套APP)


執行畫面:

版本歷程:
20130624
==> v1.10 發佈
(1)增加進入程式速度
(2)現在可以在背景運作了!!

20130621
--> v1.0 google play 上架

Google Maps 崁入式參數筆記

Google Maps嵌入參數
相關介紹
http://jax-work-archive.blogspot.tw/2011/07/google-maps.html
輸入範例
http://maps.google.com/maps?f=d&saddr=25.037525,121.56378199999995&daddr=25.063623,121.502297&hl=tw&dirflg=r



f=控制查詢表單的顯示風格。
f=d顯示成路徑規劃表單(有兩個輸入框,始點、終點)

Directions/路徑規劃
saddr= 出發點地址。
daddr=目標地址。 
“+to:” 可以使用+to:子句增加多地點線路規劃時的目標地址信息,比如daddr=大石洞村+to:馬欄廣場+to:棠梨溝
mra ?? 此參數涵義未知,可能的取值:dm/dpe/cc/ls…
mrcr ??此參數涵義未知,可能的取值:0
mrsp解析座標到街名。
mrsp=0打開從座標解析街名
mrsp=1關閉從座標解析街名
mrad= 附加目標地址。如果你的行程有三個地點,你可以用saddr=,daddr=和mrad=表示,而不採用+to:子句。
dirflg 路線類型。
dirflg=h避免高速公路。
dirflg=t避免收費路段。
dirflg=r採用公共交通。僅在一些區域可用。還可以提出附加的時間信息。
dirflg=w步行方式。仍在測試狀態。
dirflg=b騎行方式。僅在某些區域可用,仍在測試狀態。

Output Control/輸出控制
hl=主機語言。僅支持一部分語言,如hl=fr表示法語


Google Geocoding API
原廠介紹
https://developers.google.com/maps/documentation/geocoding/?hl=zh-tw

輸入範例
https://maps.googleapis.com/maps/api/directions/json?origin=25.037525,121.56378199999995&destination=25.047924,121.51708099999996&sensor=false
https://maps.googleapis.com/maps/api/directions/json?origin=25.037525,121.56378199999995&destination=25.063623,121.502297&sensor=false&mode=walking
https://maps.googleapis.com/maps/api/directions/json?origin=25.037525,121.56378199999995&destination=25.063623,121.502297&sensor=false&mode=bicycling
https://maps.googleapis.com/maps/api/directions/json?origin=25.037525,121.56378199999995&destination=25.063623,121.502297&sensor=false&mode=driving

搜尋附近地區的方式
https://maps.google.com/?q=加油站&near=龍華科技大學
上述方法無法查到所要的結果
near 後方要接的參數應為 地方名稱,實際地址 or 實際地址
範例
https://maps.google.com/?q=加油站&near=龍華科技大學,333台灣桃園縣龜山鄉萬壽路一段300號

或使用 near=25.024173,121.401817
範例:
https://maps.google.com/?q=加油站&near=25.024173,121.401817

2013年6月10日 星期一

取得自定 ListView 中的 Widget,如 TextView 的值

利用 findViewById 即可
程式碼:
以下為監聽 OnItemClickListener 事件
//==============================
@Override
public void onItemClick(AdapterView parent, View view, int position, long id) {
Log.i("==MainGo==", "進入 listView onItemClick 區段");
TextView tv = (TextView)view.findViewById(R.id.tv_list_type);
Log.i("==MainGo==", tv.getText().toString());
}




自定 listView 的 xml 檔:

    android:id="@+id/TableLayout1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/tv_show_text_list" >

            android:id="@+id/tableRow1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" >

                    android:id="@+id/tv_list_type"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/str_list_type"
            android:textAppearance="?android:attr/textAppearanceSmall"
             />
     
                    android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/str_list_go"
            android:textAppearance="?android:attr/textAppearanceSmall"
             />      

                    android:id="@+id/tv_list_name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/str_list_name"
            android:textAppearance="?android:attr/textAppearanceSmall"
             />


【參考網頁】http://stackoverflow.com/questions/15678281/get-spacial-content-of-selected-item-in-listview-in-android
   



2013年6月6日 星期四

如何使用 DialogFragment 做出自己的 DatePickerDialog 並將時間設定值設定在EditText元件中

自訂一個 class extends DialogFragment
public class MyDialogFragment extends DialogFragment implements OnDateSetListener{

@Override
public void onDateSet(DatePicker view, int year, int monthOfYear,
int dayOfMonth) {

String mYear = String.valueOf(year);
String mMonth = (monthOfYear+1 > 9)? (monthOfYear+1) +"" : "0" + (monthOfYear+1);
String mDay = (dayOfMonth > 9)? (dayOfMonth) +"" : "0" + (dayOfMonth);

EditText etday = (EditText)getActivity().findViewById(R.id.et_birthday);
etday.setText(mYear + mMonth + mDay);
}


@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {

final Calendar c = Calendar.getInstance();
int Year = c.get(Calendar.YEAR);
int Month = c.get(Calendar.MONTH);
int Day = c.get(Calendar.DAY_OF_MONTH);
       
   return new DatePickerDialog(getActivity(), this, Year, Month, Day);
}
}

在要顯示Dialog 的 Activity 使用
MyDialogFragment myDateDialog = new MyDialogFragment();
myDateDialog.show(getFragmentManager(), "datePicker");

即可...

紅色部分為 layout 中的 EditText

2013年6月2日 星期日

Android eclipse logcat 錯誤排解清單

只要有遇到就會加進這篇

Unexpected value from nativeGetEnabledTags: 0
http://stackoverflow.com/questions/13416142/unexpected-value-from-nativegetenabledtags-0

“com.android.exchange.ExchangeService has leaked …” error when running emulator [closed]
http://stackoverflow.com/questions/14111677/com-android-exchange-exchangeservice-has-leaked-error-when-running-emulato
http://stackoverflow.com/questions/13765122/various-android-logcat-errors

Android LogCat device disconnected
: E/(): Device disconnected
http://stackoverflow.com/questions/15169115/android-logcat-device-disconnected

Android 移除狀態列、標題(全螢幕),螢幕固定方向,取得螢幕大小

Android 單一頁面移除狀態列、移除標題(全螢幕)

requestWindowFeature(Window.FEATURE_NO_TITLE);      getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);

全部頁面移除狀態列、移除標題(全螢幕)

AndroidManifest.xml中在起始的activity中加入
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"



限制應用程式只能直立,禁止橫向

setRequestedOrientation( ActivityInfo.SCREEN_ORIENTATION_PORTRAIT );
or AndroidManifest.xml:
android:screenOrientation="portrait" (指定為直向) 
android:configChanges="keyboard|keyboardHidden|orientation" (告訴系統,我要自己處理轉向問題) 
需要在 Manifest.xml 中加上底下的敘述。

設定螢幕強迫旋轉 固定在哪一個方向

int nOrientation = getRequestedOrientation(); 
if (nOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) 
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 
else 
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 
需要在 Manifest.xml 中加上底下的敘述。
【參考範例】
http://androidbiancheng.blogspot.tw/2011/07/setrequestedorientation.html
http://androidbiancheng.blogspot.tw/2010/10/java-setrequestedorientation.html

解決倒退鍵無法直接退出應用程式問題

    @Override
    protected void onDestroy() {
     super.onDestroy();
     android.os.Process.killProcess(android.os.Process.myPid()); 
    }

取得螢幕大小

DisplayMetrics metrics = new DisplayMetrics();   
        getWindowManager().getDefaultDisplay().getMetrics(metrics);
TextView TextView1 = (TextView)findViewById(R.id.TextView01);

        TextView1.setText("手機螢幕大小為 "+metrics.widthPixels+" X "+metrics.heightPixels);

Related Posts Plugin for WordPress, Blogger...