2014年6月9日 星期一

Android apk 檔案上傳 Dropbox

有鑑於執行時還沒要開始上傳至Google商店,可以藉由Dropbox來放置APK檔測試
1.開啟Dropbox資料夾->在APK檔案上按右鍵->分享Dropbox連結
2.此時會複製連結,將其貼在網址 ex:https://www.dropbox.com/s/xxxxxxxxx/Android.apk
3.將www改成dl ex:https://dl.dropbox.com/s/xxxxxxxxx/Android.apk
4.輸入此網址即可自動立即下載apk檔案,不須手動點選下載。

Android GPS 定位 距離 偵測

開車照相偵測app都會偵測某個點有照相偵測機,然後發出警告,此app會用到GPS與Broadcast功能。需建立GPSService.java與GPSReceiver.java檔(與MainActivity.java同資料夾)
1.activity_main.xml
輸入接近目標的經緯度,打勾啟動

  
   
  
  
  
  

2.AndroidManifest.xml
加入GPSReceiver接收功能與GPSService廣播功能,VIBRATE手機震動功能,ACCESS_FINE_LOCATION定位功能。



        
            
                
            
        

        
3.MainActivity.java
 private EditText lat, lon;
 private CheckBox checkBox_service;
 private TextView output;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  lat = (EditText) findViewById(R.id.txtLat);
  lon = (EditText) findViewById(R.id.txtLong);
  checkBox_service = (CheckBox) findViewById(R.id.checkBox_service);
  output = (TextView) findViewById(R.id.output);
  if (checkBox_service.isChecked()) {
   start_Click(); //啟動功能
  } else {
   stop_Click(); //停止功能
  }
 }
 public void start_Click() {
  float latitude = Float.parseFloat(lat.getText().toString()); //取得輸入座標
  float longitude = Float.parseFloat(lon.getText().toString()); //取得輸入座標
  Intent intent = new Intent(this, GPSService.class); //送至GPSService.java
  intent.putExtra("LATITUDE", latitude); //發送座標至GPSService
  intent.putExtra("LONGITUDE", longitude); //發送座標至GPSService
  startService(intent);
  output.setText("服務啟動中");
 }

 public void stop_Click() {
  Intent intent = new Intent(this, GPSService.class);
  stopService(intent);
  output.setText("服務停止中");
 }
4.GPSService.java
import android.app.Service;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;

public class GPSService extends Service implements LocationListener {
 private LocationManager manager;
 private boolean isInArea;
 private double latitude, longitude;

 @Override
 public void onCreate() {

  manager = (LocationManager) getSystemService(LOCATION_SERVICE);
  manager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 10000, 1,
    this);
  manager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, 1,
    this);
  isInArea = false; //是否在範圍內
 }

 @Override
 public int onStartCommand(Intent intent, int flags, int startId) {
  try {
   latitude = (double) intent.getFloatExtra("LATITUDE1", 22.6297370f); //取得座標
   longitude = (double) intent.getFloatExtra("LONGITUDE1", 120.3278820f); //取得座標
  } catch (NullPointerException e) {
   Log.i("GPSService","NullPointException");
  }
  Log.d("GPSService", "lat/long: " + latitude + ": " + longitude);
  return START_STICKY;
 }

 @Override
 public void onDestroy() {
  manager.removeUpdates(this); //移除定位服務更新
 }

 @Override
 public void onLocationChanged(Location current) {
  // TODO Auto-generated method stub
  if (current == null)
   return;
  Location dest = new Location(current); //取得現在位置
  dest.setLatitude(latitude); //取得現在位置座標
  dest.setLongitude(longitude); //取得現在位置座標
  float distance = current.distanceTo(dest); //計算目標位置與現在位置距離
  if (distance < 1000.0) { //當目標小於1公里時
   if (isInArea == false) { //在區域內
    Intent intent = new Intent("android.broadcast.LOCATION"); //啟動廣播服務
    sendBroadcast(intent); //發送廣播
    isInArea = true; //是否在區域內:true
   }
  } else {
   isInArea = false; //是否在區域內:false
  }

 }

 @Override
 public void onStatusChanged(String provider, int status, Bundle extras) {
  // TODO Auto-generated method stub

 }

 @Override
 public void onProviderEnabled(String provider) {
  // TODO Auto-generated method stub

 }

 @Override
 public void onProviderDisabled(String provider) {
  // TODO Auto-generated method stub

 }

 @Override
 public IBinder onBind(Intent intent) {
  // TODO Auto-generated method stub
  return null;
 }

}

5.GPSReceiver.java
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.os.Vibrator;

public class GPSReceiver extends BroadcastReceiver {
 static int id = 70000;
 @SuppressWarnings("deprecation")
 @Override
 public void onReceive(Context context, Intent intent) {
  //Notification
  NotificationManager notificationManager = (NotificationManager) context
    .getSystemService(android.content.Context.NOTIFICATION_SERVICE);

  Notification notification = new Notification(R.drawable.ic_launcher,
    "您已經接近目標", System.currentTimeMillis()); //跳出Notification訊息
  Intent newintent = new Intent(context, MainActivity.class);
  PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
    newintent, 0);
  notification.setLatestEventInfo(context, "再接近就要被拍了!!", null, contentIntent);

  notificationManager.notify(id++, notification);
  
  //手機震動
  Vibrator vibrator = (Vibrator) context
    .getSystemService(Context.VIBRATOR_SERVICE);
  vibrator.vibrate(500); // 半秒
 }
}

參考來源:
http://goo.gl/BbbtPe
http://hscc.cs.nctu.edu.tw/~lincyu/Android/Chapter7.pdf

2014年6月5日 星期四

Android Splash Screen 開啟畫面

每個app都有開啟畫面,讓app有時間可以啟動一些功能
準備一張圖檔放在res⇒drawable-hdpi資料夾裡
1.AndroidManifest.xml
android:name="Your_package.SplashScreen"⇒⇒⇒⇒Your_package 你的package="xxx.xxxx.xxxxxx"
android:screenOrientation="portrait"⇒⇒⇒⇒landscape-橫屏,portrait-豎屏
action android:name="android.intent.action.MAIN"⇒⇒⇒⇒啟動點
category android:name="android.intent.category.LAUNCHER"⇒⇒⇒⇒啟動圖示

 
        
            
                

                
            
        
2.activity_splash.xml
在res⇒layout建立activity_splash.xml檔案
android:src="@drawable/load"⇒⇒⇒⇒load為圖檔名稱

 
    

    
 

3.SplashScreen.java
在跟MainActivity.java檔案同一個位置建立SplashScreen.java
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
 
public class SplashScreen extends Activity {
 
    // Splash screen timer
    private static int SPLASH_TIME_OUT = 3000; //開啟畫面時間(3秒)
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_splash);
 
        new Handler().postDelayed(new Runnable() {
 
            /*
             * Showing splash screen with a timer. This will be useful when you
             * want to show case your app logo / company
             */
 
            @Override
            public void run() {
                // This method will be executed once the timer is over
                // Start your app main activity
                Intent i = new Intent(SplashScreen.this, MainActivity.class); //MainActivity為主要檔案名稱
                startActivity(i);
 
                // close this activity
                finish();
            }
        }, SPLASH_TIME_OUT);
    }
 
}
參考來源:http://www.androidhive.info/2013/07/how-to-implement-android-splash-screen-2/

2014年6月4日 星期三

Android Sharedpreferences 儲存設定

一些app都會有設定功能,利用Sharedpreferences可以將設定好的參數儲存起來
1.activity_main.xml


2.MainActivity.java
 private CheckBox checkBox1;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  output = (TextView) findViewById(R.id.output);
  checkBox1 = (CheckBox) findViewById(R.id.checkBox1);
  checkBox1.setChecked(getFromSP("cb1")); // checkBox讀取設定
  checkBox_service.setOnCheckedChangeListener(new CheckBox.OnCheckedChangeListener() { //監聽checkBox改變狀態
   @Override
   public void onCheckedChanged(CompoundButton buttonView,
     boolean isChecked) {
    // TODO Auto-generated method stub
    if (checkBox1.isChecked()) { //如果有打勾(true)
     saveInSp("cb1", isChecked); // 儲存打勾設定
     output.setText("啟動");
    } else { //如果沒打勾(false)
     saveInSp("cb1", isChecked);// 儲存沒打勾設定
     output.setText("關閉");
    }
   }

  });
 }
 /* 讀取設定 */
 private boolean getFromSP(String key) {
  SharedPreferences preferences = getApplicationContext()
    .getSharedPreferences("PROJECT_NAME",
      android.content.Context.MODE_PRIVATE); //PROJECT_NAME專案名,android.content.Context.MODE_PRIVATE默認設定
  return preferences.getBoolean(key, false); //沒有key值時,回傳false
 }
 /* 儲存設定 */
 private void saveInSp(String key, boolean value) {
  SharedPreferences preferences = getApplicationContext()
    .getSharedPreferences("PROJECT_NAME",
      android.content.Context.MODE_PRIVATE); //PROJECT_NAME專案名,android.content.Context.MODE_PRIVATE默認設定
  SharedPreferences.Editor editor = preferences.edit(); //建立SharedPreferences編輯器
  editor.putBoolean(key, value); //利用編輯器加入屬性putBoolean(String key, boolean value),putFloat(String key, float value),putInt(String key, int value),putLong(String key, long value),putString(String key, String value)
  editor.commit(); //將數據儲存
 }

參考來源:http://stackoverflow.com/questions/10016752/saving-checkbox-states

2014年6月3日 星期二

Android google map 空白畫面

當使用google map出現一片空白,只有出現左下角有google mark,還有+-縮放功能時 基本上有四種可能,常見的為key用錯
1.沒有使用android-support-v4.jar
google map建立方法:http://cheng-min-i-taiwan.blogspot.tw/2013/04/google-maps-android-api-v2-android.html
 
2.模擬器要選擇使用Google APIs,不是Android x.x. version。

3.一般建立google map方法的網頁會要求申請一個google map API key來使用,實際上使用用原本給的key【Key for browser apps (with referers) 】就好

4.要安裝google_play_services,選擇File > Import > Android > Existing Android Code Into Workspace 點next然後點Browse,google-play-services_lib放在你的android-sdks資料夾裡的/extras/google/google_play_services/libproject/google-play-services_lib

來源:http://stackoverflow.com/questions/14216205/google-map-android-api-v2-sample-code-not-working

2014年5月30日 星期五

Android 【很抱歉,xxx已停止】

當遇到【很抱歉,xxx已停止】時,查看LogCat,找Caused by那行會顯示甚麼原因跳出錯誤, 下面那行會顯示哪個檔的第幾行出錯(java:xx),NullPointerException為常見空值錯誤, 此時用if或try catch來除錯
if else
if(someObject != null) {
    someObject.doSomething(); //錯誤行放裡面
} else {
   Log.i("Tag","空值"); // do something other
}
try catch
try {
    someObject.doSomething(); //錯誤行放裡面
} catch(NullPointerException e) {
    Log.i("Tag","空值"); // do something other
}
參考來源:http://stackoverflow.com/questions/2931065/how-to-handle-nullpointerexception-in-java

2014年5月29日 星期四

Android Exit

離開程式時。跳出框框告知是否離開 1.MainActivity.java
/*離開程式*/
 @Override
 public boolean onKeyDown(int keycode, KeyEvent event) {
  if (keycode == KeyEvent.KEYCODE_BACK) {
   closeApp(); //當按下離開按鍵時,運行closeApp()
   return true;
  }
  return super.onKeyDown(keycode, event);
 }

 public void closeApp() {
  new AlertDialog.Builder(MainActivity.this) //建立跳出框框,MainActivity為主程式名稱
    .setTitle("確定離開本程式?") //設定離開標語
    .setNegativeButton("離開", new DialogInterface.OnClickListener() { //離開按鈕監聽事件
     public void onClick(DialogInterface dialog, int which) { //按下後執行動作
      android.os.Process.killProcess(android.os.Process
        .myPid()); //殺死進程,離開後將不會再運行任何功能
     }
    })
    .setPositiveButton("繼續", new DialogInterface.OnClickListener() { //繼續按鈕監聽事件
     public void onClick(DialogInterface dialog, int which) { //按下後繼續程式
     }
    }).show();
 }
2.其他AlertDialog API還可設定圖片setIcon,訊息setMessage等,參閱 AlertDialog API:http://developer.android.com/reference/android/app/AlertDialog.html