參考資訊 : [多媒体] 音量调节
參考資訊 : [索引汇总帖] 【eoeAndroid社区索引】android设备功能之音量教程实例汇总
參考資訊 : How to capture key events from bluetooth headset with android
2015年12月30日 星期三
Android-MediaPlayer 音樂播放
import android.app.Activity;
import android.media.MediaPlayer;
import android.os.Bundle;
public class MainActivity extends Activity {
private MediaPlayer mediaPlayer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
mediaPlayer = new MediaPlayer();
mediaPlayer = MediaPlayer.create(this, R.raw.lucky_star);
mediaPlayer.start();
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
}
參考資訊 : 使用多媒體播放器(MediaPlayer)播放MP3音樂
參考資訊 : 音樂播放器(MediaPlayer)
2015年12月26日 星期六
Android-ListView 和 CheckBox 問題
不知道是否有大大遇過類似以下情況 :
比如有 30 筆資料
點選第 1 筆後
竟然在 2X 筆突然出現被勾選的狀態
If you check first checkbox and slide down, Actually the twentieth checkbox
was checked.
解決辦法 :
1 . 把被點選的位置記錄下來
2 . 生成 CheckBox 時去判斷是否要被勾選
參考資料 : ListView点击checkbox其他checkbox也被同时选中的问题
比如有 30 筆資料
點選第 1 筆後
竟然在 2X 筆突然出現被勾選的狀態
If you check first checkbox and slide down, Actually the twentieth checkbox
was checked.
解決辦法 :
1 . 把被點選的位置記錄下來
2 . 生成 CheckBox 時去判斷是否要被勾選
import java.util.HashMap;
import java.util.List;
import android.annotation.SuppressLint;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.TextView;
public class MyAdapter extends BaseAdapter{
private HashMap<Integer, Boolean> hashMap = new HashMap<Integer,Boolean>();
.
.
.
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Elements elements = null;
if (convertView == null) {
.
.
.
} else {
.
.
.
}
elements.checkBox1.setOnCheckedChangeListener(new OnCheckedChangeListener(){
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked)
{
hashMap.put(position, isChecked);
}else{
hashMap.remove(position);
}
}});
elements.checkBox1.setChecked(hashMap.get(position)==null? false : true);
return convertView;
}
}
參考資料 : ListView点击checkbox其他checkbox也被同时选中的问题
Android-Copy project and rename package
If you want to create new project form the project ( A -> A' )
You must :
1 . rename package name
2 . AndroidManifest registered activity、service、package... must change package name
3 .Change def packageName on build.gradle
4 . rebuild project
You must :
1 . rename package name
2 . AndroidManifest registered activity、service、package... must change package name
3 .Change def packageName on build.gradle
4 . rebuild project
2015年12月22日 星期二
2015年12月21日 星期一
Android-文字 轉 語音 TTS
import java.util.Locale;
import android.content.Context;
import android.speech.tts.TextToSpeech;
public class MyTTS implements TextToSpeech.OnInitListener{
private Context context;
private TextToSpeech mTextToSpeech = null;
private boolean isLoaded = false;
// initTTS
public MyTTS(Context context){
try {
this.context = context;
this.mTextToSpeech = new TextToSpeech(context, this);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS)
{
mTextToSpeech.setLanguage(Locale.US);
isLoaded = true;
}
else
{
isLoaded = false;
}
}
// stop action about tts
public void close(){
if(mTextToSpeech != null)
{
mTextToSpeech.stop();
mTextToSpeech.shutdown();
}
}
public void queueSpeak(String text) {
if (isLoaded)
mTextToSpeech.speak(text, TextToSpeech.QUEUE_ADD, null);
}
public void flushSpeak(String text) {
if (isLoaded)
mTextToSpeech.speak(text, TextToSpeech.QUEUE_FLUSH, null);
}
}
參考資料 : Android TextToSpeech Example
Android-防丟器為例
在還沒開始前,想必大家對 Bluetooth LE Scanner 不陌生吧
在開始編寫前可以先拿上方的應用程式操作看看
檢查手機版本和有無開啟藍芽
/** 初始化 */
public boolean initialize() {
// For API level 18 and above, get a reference to BluetoothAdapter through
// BluetoothManager.
if (bluetoothManager == null) {
bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
if (bluetoothManager == null) {
Log.e(TAG, "Unable to initialize BluetoothManager.");
return false;
}
}
bluetoothAdapter = bluetoothManager.getAdapter();
if (bluetoothAdapter == null) {
Log.e(TAG, "Unable to obtain a BluetoothAdapter.");
return false;
}
return true;
}
裝置連線
/** 連線至藍芽裝置 */
public boolean connect(final String address) {
if (bluetoothAdapter == null || address == null) {
Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
return false;
}
// Previously connected device. Try to reconnect.
if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress)
&& bluetoothGatt != null) {
Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection.");
if (bluetoothGatt.connect()) {
mConnectionState = STATE_CONNECTING;
return true;
} else {
return false;
}
}
final BluetoothDevice device = bluetoothAdapter.getRemoteDevice(address);
if (device == null) {
Log.w(TAG, "Device not found. Unable to connect.");
return false;
}
bluetoothGatt = device.connectGatt(this, false, mGattCallback);
Log.d(TAG, "Trying to create a new connection.");
mBluetoothDeviceAddress = address;
mConnectionState = STATE_CONNECTING;
return true;
}
與裝置離線
public void disconnect() {
if (bluetoothAdapter == null || bluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
bluetoothGatt.disconnect();
}
關閉藍芽
public void close() {
if (bluetoothGatt == null) {
return;
}
Log.w(TAG, "mBluetoothGatt closed");
mBluetoothDeviceAddress = null;
bluetoothGatt.close();
bluetoothGatt = null;
}
連線後的回調
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
mConnectionState = STATE_CONNECTED;
broadcastUpdate(intentAction);
Log.i(TAG, "Connected to GATT server.");
Log.i(TAG, "Attempting to start service discovery:" +
bluetoothGatt.discoverServices());
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
mConnectionState = STATE_DISCONNECTED;
Log.i(TAG, "Disconnected from GATT server.");
disconnect();
close();
}
broadcastUpdate(intentAction);
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
enableNotification();
} else {
Log.w(TAG, "onServicesDiscovered received: " + status);
}
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status) {
Log.w(TAG, "onCharacteristicRead received: " + characteristic.getValue());
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
Log.w(TAG, "onCharacteristicChanged received: " + characteristic.getValue());
}
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicWrite(gatt, characteristic, status);
Log.w(TAG, "onCharacteristicWrite received: ");
}
};
新增服務提醒
public void enableNotification()
{
// is support SERVICE
BluetoothGattService Service = bluetoothGatt.getService(SERVICE_UUID);
if (Service == null) {
Log.w(TAG, "service not found!");
return;
}
// is support Characteristic
BluetoothGattCharacteristic Char = Service.getCharacteristic(CHARACTERISTIC_UUID);
if (Char == null) {
Log.w(TAG, "Tx charateristic not found!");
return;
}
bluetoothGatt.setCharacteristicNotification(Char,true);
BluetoothGattDescriptor descriptor = Char.getDescriptor(CCCD);
final byte[] ENABLE_NOTIFICATION_VALUE__ = {0x01};
descriptor.setValue(ENABLE_NOTIFICATION_VALUE__);
bluetoothGatt.writeDescriptor(descriptor);
}
取得所有服務
for(BluetoothGattService bluetoothGattService: gatt.getServices())
{
Log.w(TAG, "----------------------------------");
Log.w(TAG, "BluetoothGattService : " + bluetoothGattService.getUuid() );
for(BluetoothGattCharacteristic bluetoothGattCharacteristic: bluetoothGattService.getCharacteristics())
{
Log.w(TAG, "BluetoothGattCharacteristic : " + bluetoothGattCharacteristic.getUuid() );
for(BluetoothGattDescriptor bluetoothGattDescriptro: bluetoothGattCharacteristic.getDescriptors())
{
Log.w(TAG, "BluetoothGattDescriptor : " + bluetoothGattDescriptro.getUuid());
if(bluetoothGattDescriptro.getValue() != null)
Log.w(TAG, "BluetoothGattDescriptor : " + bluetoothGattDescriptro.getValue());
}
}
}
參考資料 : AndroidとBLE
參考資料 : NordicSemiconductor/Android-nRF-Toolbox
參考資料 : BLE Health Devices: First Steps with Android
參考資料 : Bluetooth Low Energy (or LE) is a very cool technology.
參考資料 : SensorTag User Guide_Android
2015年12月18日 星期五
Android-判斷手機 網路 藍芽 狀態
手機裝置狀態
Check Cellphone State : Bluetooth、NetWork
權限
參考資料 : 【Android】檢查網路連線狀態 Connectivity Network Active State
歡迎轉載,請註明出處。
Check Cellphone State : Bluetooth、NetWork
權限
<!-- 藍芽 -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<!-- 網路 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
/**
* 裝置狀態
*/
public class DeviceState {
/** 網路是否連線 */
public static boolean isNetWorkConnection(Context context){
boolean isConnection = false;
ConnectivityManager mConnectivityManager =
(ConnectivityManager) context.getApplicationContext()
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo mNetworkInfo = mConnectivityManager.getActiveNetworkInfo();
if(mNetworkInfo != null)
if(mNetworkInfo.isConnected())
isConnection = true;
return isConnection;
}
/** 裝置是否支援低功率藍芽 */
public static boolean isSupportBle(){
boolean isSupport = false;
BluetoothAdapter mBluetoothAdapter =
BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter != null)
isSupport = true;
return isSupport;
}
}
參考資料 : 【Android】檢查網路連線狀態 Connectivity Network Active State
歡迎轉載,請註明出處。
2015年12月17日 星期四
Android-RecyclerView Sample 範例 Kotlin
更新日期:20189116 新增範例( kotlin )
雖然有 ListView 和 GridView 顯示資訊
但還要另外寫選配器
Google 又另外推出 RecyclerView
聞說效率比前 2 個 View 效率更高
話不多說
先來個簡單流程說明吧
1 . 首先設計要顯示表格的畫面內容
2 . 將剛剛設計的內容格式放置選配器內
3 . 將資料放置選配器中
4 . 依照不同的需求顯示
直接來個範例
1 . build.gradle 先匯入以下
2 . 新增元素介面
3 . 設定頁面參數
4 . 設定選配器
5 . 在主畫面宣告
6 .
( LinearLayoutManager )
(GridLayoutManager)
參考資料 : Creating Lists with RecyclerView in Android
參考資料 : RecyclerView使用详解(一)
雖然有 ListView 和 GridView 顯示資訊
但還要另外寫選配器
Google 又另外推出 RecyclerView
聞說效率比前 2 個 View 效率更高
話不多說
先來個簡單流程說明吧
1 . 首先設計要顯示表格的畫面內容
2 . 將剛剛設計的內容格式放置選配器內
3 . 將資料放置選配器中
4 . 依照不同的需求顯示
直接來個範例
1 . build.gradle 先匯入以下
compile 'com.android.support:cardview-v7:26.1.0'
compile 'com.android.support:recyclerview-v7:26.1.0'
2 . 新增元素介面
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/item_record_1_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
app:srcCompat="@mipmap/ic_launcher" />
<TextView
android:id="@+id/item_record_1_text"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="TextView" />
</LinearLayout>
</LinearLayout>
3 . 設定頁面參數
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.light.blue.counter.R;
public class MyViewHolder_1 extends RecyclerView.ViewHolder {
public ImageView mImageView;
public TextView mTextView;
public MyViewHolder_1(View view) {
super(view);
// 添加預設的模組
mImageView = view.findViewById(R.id.item_record_1_img);
mTextView = view.findViewById(R.id.item_record_1_text);
}
}
4 . 設定選配器
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.light.blue.adpater.view.MyViewHolder_1;
import com.light.blue.counter.R;
import java.util.List;
public class MyAdapter_1 extends RecyclerView.Adapter<MyViewHolder_1> {
private List<String> mList;
public MyAdapter_1(List<String> list) {
mList = list;
}
@Override
public int getItemCount() {
return mList.size();
}
@Override
public void onBindViewHolder(MyViewHolder_1 holder, int position) {
holder.mTextView.setText(mList.get(position).toString());
}
@Override
public MyViewHolder_1 onCreateViewHolder(ViewGroup viewGroup, int viewType) {
View view = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.item_record_1, viewGroup, false);
return new MyViewHolder_1(view);
}
}
5 . 在主畫面宣告
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycleView_recyclerList"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical">
</android.support.v7.widget.RecyclerView>
</android.support.constraint.ConstraintLayout>
6 .
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.LinearLayoutManager
import com.light.blue.adpater.MyAdapter_1
import com.light.blue.sql.until.MyDatabaseHandler
import kotlinx.android.synthetic.main.activity_recycleview.*
import java.util.*
class RecycleListActivity : AppCompatActivity() {
private lateinit var myDatabaseHandler: MyDatabaseHandler;
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_recycleview)
myDatabaseHandler = MyDatabaseHandler(this);
var listStr = ArrayList<String>();
listStr.add("小明");
listStr.add("小王");
listStr.add("小黃");
listStr.add("小黑");
listStr.add("小白");
recycleView_recyclerList.layoutManager = LinearLayoutManager(this);
// recycleView_recyclerList.layoutManager = GridLayoutManager(this, 3);
recycleView_recyclerList.adapter = MyAdapter_1(listStr);
}
}
(GridLayoutManager)
參考資料 : Creating Lists with RecyclerView in Android
參考資料 : RecyclerView使用详解(一)
參考資料 : RecyclerView使用详解(二)
2015年12月16日 星期三
Android-Create New Project
想必各位大大心目中有一些想實踐的App
但要如何開始?
建議 : 不要一想到就直接開始動工
不然後繼無力就很容易失去原有的方向
不做申論只需簡單問自己
然後以最簡短的一句話寫在紙上
首先,先分析 3W1H !!!
1 . Why?
為甚麼要寫此 App?
2 . Who?
此 App 使用對象為?
3 . What?
未來展望?想要的目的?
4 . How?
要如何做?
如果此問題都能回答出來
因該就算是踏出第一步了
--------------------------------------------------
接下來就是實作分析
1 . Functional Map
2 . Flow
3 . UI design
但要如何開始?
建議 : 不要一想到就直接開始動工
不然後繼無力就很容易失去原有的方向
不做申論只需簡單問自己
然後以最簡短的一句話寫在紙上
首先,先分析 3W1H !!!
1 . Why?
為甚麼要寫此 App?
2 . Who?
此 App 使用對象為?
3 . What?
未來展望?想要的目的?
4 . How?
要如何做?
如果此問題都能回答出來
因該就算是踏出第一步了
--------------------------------------------------
接下來就是實作分析
1 . Functional Map
2 . Flow
3 . UI design
Android-水波紋特效 ripple
20170311 新增:ImageButton has ripple effect
Google 在 5.0 有新增一些特效
最明顯的例子 : 按鍵有水波紋特效
至於能不能讓使用者接受
只能見仁見智了
1 . 在專案內 新增 drawable-v21
2 . 用 ripple 包覆元素
3 . 物件套用剛剛客製的 drawable
注意 : 最小 SDK 版本為 21
參考資訊 : Lollipop RippleDrawable vs Selector for Pre-Lollipop
參考資訊 : How to Add Ripple Effect/Animation to a Android Button
參考資料:Apply Material Design Touch Ripple to ImageButton?
--------------------------------------------------------
如果手機版本比較低可以參考 :
參考資訊 : material-ripple
參考資訊 : RippleEffect
參考資訊 : 內有連結
Google 在 5.0 有新增一些特效
最明顯的例子 : 按鍵有水波紋特效
至於能不能讓使用者接受
只能見仁見智了
1 . 在專案內 新增 drawable-v21
2 . 用 ripple 包覆元素
3 . 物件套用剛剛客製的 drawable
注意 : 最小 SDK 版本為 21
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/white">
<item android:drawable="@drawable/ic_l"/>
</ripple>
參考資訊 : Lollipop RippleDrawable vs Selector for Pre-Lollipop
參考資訊 : How to Add Ripple Effect/Animation to a Android Button
參考資料:Apply Material Design Touch Ripple to ImageButton?
--------------------------------------------------------
如果手機版本比較低可以參考 :
參考資訊 : material-ripple
參考資訊 : RippleEffect
參考資訊 : 內有連結
2015年12月15日 星期二
2015年12月14日 星期一
Android-Take Photo and save file
1 . 新增權限
2 . 設定 RequestCode
3 . 開啟相機
4 . 接收拍照結果
5 . 如果要有儲存照片功能
參考資料 : Android : Use Camera Activity for Thumbnail and FullSize Image
參考資料 : 【Android】開啟相機-照相功能與相簿-相片集並讀取相片匯入至程式
歡迎轉載,請註明出處。
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
2 . 設定 RequestCode
public static final int TAKE_PHOTO_IMAGE_CODE = 1234;
3 . 開啟相機
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
startActivityForResult(intent, TAKE_PHOTO_IMAGE_CODE);
4 . 接收拍照結果
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == TAKE_PHOTO_IMAGE_CODE)
{
//Check if data in not null
if (data != null)
{
Bitmap bitmap = (Bitmap)data.getExtras().get("data");
imageView.setImageBitmap(bitmap);
}
}
}
5 . 如果要有儲存照片功能
public static final String FileName = "Hello";
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
//Check that request code matches ours:
if (requestCode == TAKE_PHOTO_IMAGE_CODE)
{
// 建立資料夾
File imageStorageFolder =
new File(Environment.getExternalStorageDirectory()+File.separator + FileName);
if (!imageStorageFolder.exists())
{
imageStorageFolder.mkdirs();
Log.d(TAG , "Folder created at: "+imageStorageFolder.toString());
}
//Check if data in not null
if (data != null)
{
String imageName = "image";
String fileNameExtension = ".jpg";
File sdCard = Environment.getExternalStorageDirectory();
String strImageStorageFolder = File.separator + FileName + File.separator;
File destinationFile =
new File(sdCard, strImageStorageFolder + imageName + fileNameExtension);
Log.d(TAG, "the destination for image file is: " + destinationFile );
if (data.getExtras() != null)
{
Bitmap bitmap = (Bitmap)data.getExtras().get("data");
//判斷照片為橫向或者為直向,並進入ScalePic判斷圖片是否要進行縮放
if(bitmap.getWidth()>bitmap.getHeight())
ScalePic(bitmap,mPhone.heightPixels);
else
ScalePic(bitmap,mPhone.widthPixels);
try
{
FileOutputStream out = new FileOutputStream(destinationFile);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
out.flush();
out.close();
}
catch (Exception e)
{
Log.e(TAG, "ERROR:" + e.toString());
}
}
}
}
}
private void ScalePic(Bitmap bitmap,int phone)
{
//縮放比例預設為1
float mScale = 1 ;
//如果圖片寬度大於手機寬度則進行縮放,否則直接將圖片放入ImageView內
if(bitmap.getWidth() > phone )
{
//判斷縮放比例
mScale = (float)phone/(float)bitmap.getWidth();
Matrix mMat = new Matrix() ;
mMat.setScale(mScale, mScale);
Bitmap mScaleBitmap = Bitmap.createBitmap(bitmap,
0,
0,
bitmap.getWidth(),
bitmap.getHeight(),
mMat,
false);
imageView.setImageBitmap(mScaleBitmap);
}
else imageView.setImageBitmap(bitmap);
}
參考資料 : Android : Use Camera Activity for Thumbnail and FullSize Image
參考資料 : 【Android】開啟相機-照相功能與相簿-相片集並讀取相片匯入至程式
歡迎轉載,請註明出處。
Java-時間 日期 增減
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
calendar.add(Calendar.DATE, 3);
String date = dateFormat.format(calendar.getTime());
System.out.println(date);
歡迎轉載,請註明出處。
2015年12月13日 星期日
Android-廣告 滑動頁面 ViewPager + PagerAdapter(一)
更新日期 : 20160116 新增索引點
更新日期 : 20160217 切換頁面監聽更改
相信各位在安裝 App 時候一定有引導教學左右滑動頁面
經過測試後
其實跟我們常用的 ListView 、GridView 大同小異
如果對 BaseAdapter 熟悉的朋友
一定很快就能上手
注意 : 要使用此功能,必須匯入 V4 包
順序
1 . 抓出畫面共同點!? ( 有些App會在最後一頁有 Button ,可以先隱藏 )
2 . 設計畫面UI
3 . 設計選配器
4 . 將 選配器放進 ViewPager ( 像 ListView )內
這次的 Sample 以單純圖片顯示
1 . cell_pager_image.xml
2 . MyPagerAdapter.java
3 . activity_main.xml (將設定好的選配器設置到 ViewPager 上
4 . MainActivity.java
如果要對頁面設定監聽器
參考資料 : Viewpager setonpagechangelistener deprecated
有關於底下原點,必須要在MainActivity設定
簡單的說必須配合監聽換頁
如果有時間會在寫一些 Sample
參考資料 : Android ViewPager Gallery Images and Texts Tutorial
參考資料 : Android通用圆点指示器——android-Universal-CircleIndicator
參考資料 : ViewPagerIndicator 分頁指示器
參考資料 : VIEW PAGER WITH CIRCULAR INDICATOR (WITHOUT ANY LIBRARY)
歡迎轉載,請註明出處。
更新日期 : 20160217 切換頁面監聽更改
相信各位在安裝 App 時候一定有引導教學左右滑動頁面
經過測試後
其實跟我們常用的 ListView 、GridView 大同小異
如果對 BaseAdapter 熟悉的朋友
一定很快就能上手
注意 : 要使用此功能,必須匯入 V4 包
順序
1 . 抓出畫面共同點!? ( 有些App會在最後一頁有 Button ,可以先隱藏 )
2 . 設計畫面UI
3 . 設計選配器
4 . 將 選配器放進 ViewPager ( 像 ListView )內
這次的 Sample 以單純圖片顯示
1 . cell_pager_image.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/imageView"
android:scaleType="fitXY"
android:layout_gravity="right" />
</LinearLayout>
2 . MyPagerAdapter.java
import android.content.Context;
import android.support.v4.view.PagerAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import java.util.List;
public class MyPagerAdapter extends PagerAdapter {
private Context context;
private List<Integer> list;
private LayoutInflater inflater;
public MyPagerAdapter(Context context, List<Integer> list) {
this.context = context;
this.list = list;
}
@Override
public int getCount() {
return list.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
inflater = (LayoutInflater)
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// 佈局
View itemView = inflater
.inflate(R.layout.cell_pager_image, container, false);
// 佈局元件內容
ImageView imageView = (ImageView)itemView.findViewById(R.id.imageView);
imageView.setImageResource(list.get(position));
// 加載
(container).addView(itemView);
return itemView;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
// LinearLayout 是以 cell_pager_image 主體變更
container.removeView((LinearLayout) object);
}
}
3 . activity_main.xml (將設定好的選配器設置到 ViewPager 上
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</android.support.v4.view.ViewPager>
</RelativeLayout>
4 . MainActivity.java
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.view.ViewPager;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends Activity implements ViewPager.OnPageChangeListener{
ViewPager viewPager;
MyPagerAdapter myPagerAdapter;
// 在專案內放的測試圖
private static final int[] pictures = { R.drawable.icon_01,
R.drawable.icon_02, R.drawable.icon_03 };
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager) findViewById(R.id.viewpager);
List<Integer> list = new ArrayList<Integer>();
for(int i : pictures){
list.add(i);
}
myPagerAdapter = new MyPagerAdapter(this, list);
viewPager.setAdapter(myPagerAdapter);
}
}
如果要對頁面設定監聽器
ViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
參考資料 : Viewpager setonpagechangelistener deprecated
有關於底下原點,必須要在MainActivity設定
簡單的說必須配合監聽換頁
如果有時間會在寫一些 Sample
參考資料 : Android ViewPager Gallery Images and Texts Tutorial
參考資料 : Android通用圆点指示器——android-Universal-CircleIndicator
參考資料 : ViewPagerIndicator 分頁指示器
參考資料 : VIEW PAGER WITH CIRCULAR INDICATOR (WITHOUT ANY LIBRARY)
歡迎轉載,請註明出處。
2015年12月12日 星期六
2015年12月11日 星期五
2015年12月7日 星期一
Android-DatePickerDialog 範例 Sample
官方日期選擇器
1 . 實作 DatePickerDialog
2 . 實作 DatePickerDialog
3 . 接回參數
歡迎轉載,請註明出處。
1 . 實作 DatePickerDialog
Calendar calendar0 = Calendar.getInstance();
DatePickerDialog dialog0 = new DatePickerDialog(this, this,
calendar0.get(Calendar.YEAR), calendar0.get(Calendar.MONTH),
calendar0.get(Calendar.DAY_OF_MONTH));
dialog0.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
dialog0.show();
2 . 實作 DatePickerDialog
....implements implements DatePickerDialog.OnDateSetListener{ ... }
3 . 接回參數
// CallBack
@Override
public void onDateSet(DatePicker view, int year, int monthOfYear,
int dayOfMonth) {
SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd");
Log.d("DateTest","Date : " + format.format(new Date()));
}
歡迎轉載,請註明出處。
2015年12月6日 星期日
2015年12月1日 星期二
Android-Fragment get Activity value
MActivity activity = (MActivity) getActivity();
String str = activity.getG1();
參考資料 : How do I pass a variable through a FragmentPagerAdapter to a Fragment?
2015年11月26日 星期四
2015年11月25日 星期三
2015年11月22日 星期日
Android-AndroidStudio GCM
更新日期 : 20160318_新增註冊ID內容
使用 AndroidStudio 為 App 添加 GCM( Google Cloud Message )
想必大大對 GMC 不陌生吧
如果不知道的沒關係
以下舉例您可能馬上就知道
1 . 安裝應用 App 三不五時就會收到擾人的通知
2 . 安裝應用 遊戲 後,突然收到開戰通知!!!
這些大多都是 推播 ( 以GCM為例 )!!!
為啥要以 GCM 為範例?
其實微軟、亞馬遜也有提供
但是以大眾來講 GCM 是最普及的
進入重點
是如何動作的
1 . 開發者向 Google 申請序號
2 . 在 App 內放置序號並且實作 GCM
3 . 成功之後會回傳 Token
4 . 開發者將 Token 傳送到指定位置存放
5 . 開發者將指定 Token 配合並發送,使用者手機就可收到訊息
步驟
1 . 申請專案序號
連結 : GoogleDevelopersConsole
參考資料 : android-gcm-tool
參考資料 : Push Notification using GCM in Android Studio | Google Cloud Messaging
使用 AndroidStudio 為 App 添加 GCM( Google Cloud Message )
想必大大對 GMC 不陌生吧
如果不知道的沒關係
以下舉例您可能馬上就知道
1 . 安裝應用 App 三不五時就會收到擾人的通知
2 . 安裝應用 遊戲 後,突然收到開戰通知!!!
這些大多都是 推播 ( 以GCM為例 )!!!
為啥要以 GCM 為範例?
其實微軟、亞馬遜也有提供
但是以大眾來講 GCM 是最普及的
進入重點
是如何動作的
1 . 開發者向 Google 申請序號
2 . 在 App 內放置序號並且實作 GCM
3 . 成功之後會回傳 Token
4 . 開發者將 Token 傳送到指定位置存放
5 . 開發者將指定 Token 配合並發送,使用者手機就可收到訊息
步驟
1 . 申請專案序號
連結 : GoogleDevelopersConsole
參考資料 : android-gcm-tool
參考資料 : Push Notification using GCM in Android Studio | Google Cloud Messaging
2015年11月21日 星期六
Java-日期/時間 格式轉換
更新日期 : 20151212 ( 新增流程 )
流程 :
1 . 資料來源
2 . 來源格式
3 . 目的格式
4 . 將來資料來源轉換成 Date (parse)
5 . 將 來源Date 套用在 目的格式 (format)
6 . 轉換成字串
歡迎轉載,請註明出處。
流程 :
1 . 資料來源
2 . 來源格式
3 . 目的格式
4 . 將來資料來源轉換成 Date (parse)
5 . 將 來源Date 套用在 目的格式 (format)
6 . 轉換成字串
try {
// 1 ( 二選一 )
// 自定義
String date = "2015/12/12 07:07:07";
// 系統時間
DateFormat dateFormat_1 = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
String date = dateFormat_1.format(new Date());
System.out.println(date);
// 2
DateFormat dateFormat_1 = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
// 3
DateFormat dateFormat_2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 4
Date date_org = dateFormat_1.parse(date);
// 5 . 6
String myDate = dateFormat_2.format(date_org);
System.out.println(myDate);
} catch (ParseException e) {
e.printStackTrace();
}
歡迎轉載,請註明出處。
2015年11月18日 星期三
Android-左右滑動圖片 Image ViewPager
參考資料 : 使用ViewPager实现左右滑动效果
參考資料 : Android实现左右滑动指引效果
參考資料 : Android通过ViewPager实现左右滑动切换图片
參考資料 : Android 基于ImageSwitcher实现的左右切换图片
參考資料 : Android Image Slideshow using ViewPager with PagerAdapter
( 有成功,但是沒壓縮造成反應遲緩,無引導點 )
若改無限制
參考資料 : Android UI设计——ViewPager中设置底部显示圆点焦点(二)
( 引導點 )
參考資料 : 用ViewPager实现欢迎引导页面
( 帶有引導點,可動態增加圖片 )
參考資料 : Android Image Slideshow using ViewPager with PagerAdapter
( 有成功,但是沒壓縮造成反應遲緩,無引導點 )
若改無限制
@Override
public int getCount() {
return mResources.length;
}
圖片來源記得要取餘數,不然會 Exception參考資料 : Android UI设计——ViewPager中设置底部显示圆点焦点(二)
( 引導點 )
參考資料 : 用ViewPager实现欢迎引导页面
( 帶有引導點,可動態增加圖片 )
2015年11月13日 星期五
Android-Google Ads 廣告置入 範例 Sample
20170311 新增:整頁廣告
想必大家都聽過寫 App 然後靠廣告賺錢
1 . 在 Gradle 內加入
2 . 在要呈現的版面新增元件
3 . 宣告元件
4 . 將 AdMob 給的序號添加在 String.xml
序號來源 以下有教學
----------------------------------------------------------------
關於廣告帳號註冊
1 . 申請 Ads 帳號
首頁
https://apps.admob.com/#home
註冊Key
https://apps.admob.com/#monetize/pubcontrols:urls
參考資料: Interstitial Ads
參考資料:Interstitial Ads 無法顯示的問題
歡迎轉載,請註明出處。
想必大家都聽過寫 App 然後靠廣告賺錢
那要如何把廣告植入在我們的心血?
其實沒有我們想像的困難
此 Sample 是以 AndroidStudio 版本為主 : 連結
如果大大是以 Eclipse 開發 請參考 : 連結
雖然網路以上有流程
但只需要自己所要的部分
1 . 在 Gradle 內加入
compile 'com.google.android.gms:play-services-ads:7.8.0'
2 . 在要呈現的版面新增元件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ads="http://schemas.android.com/apk/res-auto"
.
.
<com.google.android.gms.ads.AdView
android:id="@+id/adView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
ads:adSize="BANNER"
ads:adUnitId="@string/banner_ad_unit_id">
</com.google.android.gms.ads.AdView>
</LinearLayout>
3 . 宣告元件
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AdView mAdView = (AdView) findViewById(R.id.adView);
AdRequest adRequest = new AdRequest.Builder().build();
mAdView.loadAd(adRequest);
.
.
}
4 . 將 AdMob 給的序號添加在 String.xml
序號來源 以下有教學
<resources>
<string name="banner_ad_unit_id">ca-app-pub-111222333444555666/555444111</string>
</resources>
----------------------------------------------------------------
關於廣告帳號註冊
1 . 申請 Ads 帳號
https://apps.admob.com/#home
註冊Key
https://apps.admob.com/#monetize/pubcontrols:urls
參考資料: Interstitial Ads
參考資料:Interstitial Ads 無法顯示的問題
歡迎轉載,請註明出處。
Android-Parse Push ParsePushBroadcastReceiver ( 三 )
在前面兩個章節有介紹如何 :
You can add key in onReciver
- String strChannel = intent.getExtras().getString("com.parse.Channel");
- String strData = intent.getExtras().getString("com.parse.Data");
2 . 將原先的註冊的 Receiver 更改
( 更改成剛剛繼承的 Receiver )
3 . 如果覺得原生的 Notification 太單調,也可以改成自己的
歡迎轉載,請註明出處。
- 初始化 Parse
- 接收 Parse Push Message
- 發送 Push Message
這次我們要做第二點的延伸
延伸?
簡單的說,Parse SDK 有預設
但我們想自己做 Design 這樣可以嗎??
Notification Icon、Notification Message ...etc.
Notification Icon、Notification Message ...etc.
當然是可以的
1 . extends ParsePushBroadcastReceiver
( ex : is ParsePushBroadcastReceiver, isn't ParseBroadcastReceiver )
( ex : is ParsePushBroadcastReceiver, isn't ParseBroadcastReceiver )
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import com.parse.ParsePushBroadcastReceiver;
public class MyParseReceiver extends ParsePushBroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d("MyParseReceiver", "action:" + action);
}
}
You can add key in onReciver
- String strChannel = intent.getExtras().getString("com.parse.Channel");
- String strData = intent.getExtras().getString("com.parse.Data");
2 . 將原先的註冊的 Receiver 更改
<receiver
android:name="com.parse.ParsePushBroadcastReceiver"
android:exported="false" >
<intent-filter>
<action android:name="com.parse.push.intent.RECEIVE" />
<action android:name="com.parse.push.intent.OPEN" />
<action android:name="com.parse.push.intent.DELETE" />
</intent-filter>
</receiver>
( 更改成剛剛繼承的 Receiver )
<receiver
android:name="MyParseReceiver"
android:exported="false" >
<intent-filter>
<action android:name="com.parse.push.intent.RECEIVE" />
<action android:name="com.parse.push.intent.OPEN" />
<action android:name="com.parse.push.intent.DELETE" />
</intent-filter>
</receiver>
3 . 如果覺得原生的 Notification 太單調,也可以改成自己的
// 將提醒功能取消
@Override
protected Notification getNotification(Context context, Intent intent) {
return null;
}
private void myNotification(...){
Notification...
}
歡迎轉載,請註明出處。
2015年11月9日 星期一
Android-Weather API
World Weather Online
Link : http://www.worldweatheronline.com/
OpenWeatherMap
Link : http://openweathermap.org/
台灣氣象資訊
雖然有資料,但送出格式有待確認
Link : http://www.worldweatheronline.com/
OpenWeatherMap
Link : http://openweathermap.org/
台灣氣象資訊
雖然有資料,但送出格式有待確認
Java-Synchronized 同步 用法 執行
想必大家都聽過 Synchronized 同步 之類的
但聽過這麼多
但是到底是啥東西??
簡單的說 : 你要使用此物件、方法,你就是要
排隊!!!
排隊!!!
排隊!!!
但是前者結束,後者要搶!!!
為啥要排隊?不是直接使用就好了嗎??
當然也行,但在銀行的例子就不可行
在同一時間只能一個人做領錢的動作
直到確認把錢交至手上為止
下一個人才能領錢或存錢
那寫哪種程式比較常遇到 ?
檔案接收完整性、資料存取之類
以下圖示針對銀行例子做圖解
( 左 : 同時領錢 , 右 : 排隊領錢 )
以下是用範例呈現 :
1 . 不使用 Synchonized
多次執行,結果皆不同。
2 . 使用 Synchonized
多次執行,結果相同。
以下是範例程式碼 : ( 請自行更改 synchronized 需求 )
Test.java
TestThread.java
注意 :
因為線程的執行本身就是不確定的
加了 Synchronizes 只能確保這段程式碼和參數
並不能保證程序的執行順序!!!
如果真的要有順序,先暫時用 Sleep 頂替。
參考資料 : [Java] Synchronized 心得
參考資料 : JAVA筆記-synchronized 同步物件資料,避免Race Condition
歡迎轉載,請註明出處。
但聽過這麼多
但是到底是啥東西??
簡單的說 : 你要使用此物件、方法,你就是要
排隊!!!
排隊!!!
排隊!!!
但是前者結束,後者要搶!!!
為啥要排隊?不是直接使用就好了嗎??
當然也行,但在銀行的例子就不可行
在同一時間只能一個人做領錢的動作
直到確認把錢交至手上為止
下一個人才能領錢或存錢
那寫哪種程式比較常遇到 ?
檔案接收完整性、資料存取之類
以下圖示針對銀行例子做圖解
( 左 : 同時領錢 , 右 : 排隊領錢 )
以下是用範例呈現 :
1 . 不使用 Synchonized
2 . 使用 Synchonized
多次執行,結果相同。
以下是範例程式碼 : ( 請自行更改 synchronized 需求 )
Test.java
public class Test {
public static void main(String[] args) {
TestThread.Threading("1");
TestThread.Threading("2");
}
}
TestThread.java
public class TestThread {
public static void Threading(String message){
new Threading(message).start();
}
public static class Threading extends Thread {
private String _strMessage;
Threading(String strMessage){
this._strMessage = strMessage;
}
public void run() {
// synchronized (TestThread.class) {
try {
for(int i=0; i < 5; i++){
Thread.sleep(1000);
System.out.println(_strMessage + " : " + i);
}
} catch (InterruptedException e) {
}
// }
}
}
}
注意 :
因為線程的執行本身就是不確定的
加了 Synchronizes 只能確保這段程式碼和參數
並不能保證程序的執行順序!!!
如果真的要有順序,先暫時用 Sleep 頂替。
參考資料 : [Java] Synchronized 心得
參考資料 : JAVA筆記-synchronized 同步物件資料,避免Race Condition
歡迎轉載,請註明出處。
2015年11月5日 星期四
Android-GreenDAO 的基本使用方式 可當小型 資料庫 - 3
如果有需要再新增欄位怎麼辦?
比如要在新增有關日期的欄位( 紅字代表新增 )
資料庫重建?
如果真的有需要新增欄位
可以直接在 Class 下新增
但要注意不要由遺漏的
沿用上一篇創立的表格 : Note
當創立完後
會產生以下兩個檔案
我們會修改此檔案
比如要在新增有關日期的欄位( 紅字代表新增 )
1 . Note.java ( 4項須更新 )
package de.greenrobot.daoexample;
// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT. Enable "keep" sections if you want to edit.
/**
* Entity mapped to table NOTE.
*/
public class Note {
private Long id;
/** Not-null value. */
private String note;
private int count;
/** Not-null value. */
private java.util.Date date;
/** Not-null value. */
private java.util.Date Hee;
public Note() {
}
public Note(Long id) {
this.id = id;
}
public Note(Long id, String note, int count, java.util.Date date, java.util.Date Hee) {
this.id = id;
this.note = note;
this.count = count;
this.date = date;
this.Hee = Hee;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
/** Not-null value. */
public String getNote() {
return note;
}
/** Not-null value; ensure this value is available before it is saved to the database. */
public void setNote(String note) {
this.note = note;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
/** Not-null value. */
public java.util.Date getDate() {
return date;
}
/** Not-null value; ensure this value is available before it is saved to the database. */
public void setDate(java.util.Date date) {
this.date = date;
}
/** Not-null value. */
public java.util.Date getHee() {
return Hee;
}
/** Not-null value; ensure this value is available before it is saved to the database. */
public void setHee(java.util.Date Hee) {
this.Hee = Hee;
}
}
2 . NoteDao.java( 5項需更新 )
package de.greenrobot.daoexample;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteStatement;
import de.greenrobot.dao.AbstractDao;
import de.greenrobot.dao.Property;
import de.greenrobot.dao.internal.DaoConfig;
import de.greenrobot.daoexample.Note;
// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
/**
* DAO for table NOTE.
*/
public class NoteDao extends AbstractDao<Note, Long> {
public static final String TABLENAME = "NOTE";
/**
* Properties of entity Note.<br/>
* Can be used for QueryBuilder and for referencing column names.
*/
public static class Properties {
public final static Property Id = new Property(0, Long.class, "id", true, "_id");
public final static Property Note = new Property(1, String.class, "note", false, "NOTE");
public final static Property Count = new Property(2, int.class, "count", false, "COUNT");
public final static Property Date = new Property(3, java.util.Date.class, "date", false, "DATE");
public final static Property Hee = new Property(4, java.util.Date.class, "Hee", false, "HEE");
};
public NoteDao(DaoConfig config) {
super(config);
}
public NoteDao(DaoConfig config, DaoSession daoSession) {
super(config, daoSession);
}
/** Creates the underlying database table. */
public static void createTable(SQLiteDatabase db, boolean ifNotExists) {
String constraint = ifNotExists? "IF NOT EXISTS ": "";
db.execSQL("CREATE TABLE " + constraint + "'NOTE' (" + //
"'_id' INTEGER PRIMARY KEY ," + // 0: id
"'NOTE' TEXT NOT NULL ," + // 1: note
"'COUNT' INTEGER NOT NULL ," + // 2: count
"'DATE' INTEGER NOT NULL ," + // 3: date
"'HEE' INTEGER NOT NULL );"); // 4: Hee
}
/** Drops the underlying database table. */
public static void dropTable(SQLiteDatabase db, boolean ifExists) {
String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "'NOTE'";
db.execSQL(sql);
}
/** @inheritdoc */
@Override
protected void bindValues(SQLiteStatement stmt, Note entity) {
stmt.clearBindings();
Long id = entity.getId();
if (id != null) {
stmt.bindLong(1, id);
}
stmt.bindString(2, entity.getNote());
stmt.bindLong(3, entity.getCount());
stmt.bindLong(4, entity.getDate().getTime());
stmt.bindLong(5, entity.getHee().getTime());
}
/** @inheritdoc */
@Override
public Long readKey(Cursor cursor, int offset) {
return cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0);
}
/** @inheritdoc */
@Override
public Note readEntity(Cursor cursor, int offset) {
Note entity = new Note( //
cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0), // id
cursor.getString(offset + 1), // note
cursor.getInt(offset + 2), // count
new java.util.Date(cursor.getLong(offset + 3)), // date
new java.util.Date(cursor.getLong(offset + 4)) // Hee
);
return entity;
}
/** @inheritdoc */
@Override
public void readEntity(Cursor cursor, Note entity, int offset) {
entity.setId(cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0));
entity.setNote(cursor.getString(offset + 1));
entity.setCount(cursor.getInt(offset + 2));
entity.setDate(new java.util.Date(cursor.getLong(offset + 3)));
entity.setHee(new java.util.Date(cursor.getLong(offset + 4)));
}
/** @inheritdoc */
@Override
protected Long updateKeyAfterInsert(Note entity, long rowId) {
entity.setId(rowId);
return rowId;
}
/** @inheritdoc */
@Override
public Long getKey(Note entity) {
if(entity != null) {
return entity.getId();
} else {
return null;
}
}
/** @inheritdoc */
@Override
protected boolean isEntityUpdateable() {
return true;
}
}
歡迎轉載,請註明出處。
2015年10月30日 星期五
Android-曲線圖 折線圖
只要有關數據分析的 App 我相信一定對曲線圖不陌生吧
今天就來做一個簡易的 Sample ( 範例 )
首先分析順序 :
activity_main.xml
MainActivity.class
LineCharView.class
範例圖示 :
參考資料:MPAndroidChart
參考資料:MPAndroidChart 教程:概述
參考資料 : Android自定义控件 -Canvas绘制折线图(实现动态报表效果)
參考資料 : Android chart tutorial: AChartEngine - Line chart, Bar chart, Range bar
參考資料 : [Andriod] 透過AChartEngine實現BarChart
參考資料 : achartengine之折线图---简单用法
歡迎轉載,請註明出處。
今天就來做一個簡易的 Sample ( 範例 )
首先分析順序 :
- 資料
- 曲線圖 折線圖 風格
- 放置目標
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/tv_title"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="@string/str_tv_title" />
<LinearLayout
android:id="@+id/chart_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_margin="8dip" >
</LinearLayout>
</LinearLayout>
MainActivity.class
package com.example.ach;
import java.util.ArrayList;
import java.util.List;
import org.achartengine.ChartFactory;
import org.achartengine.chart.PointStyle;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.model.XYSeries;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYSeriesRenderer;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.widget.LinearLayout;
public class MainActivity extends Activity {
private View mChart;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
List<String> list_D = new ArrayList<String>();
for(int i = 0; i <10; i++){
list_D.add("" + 100+i);
}
List<Integer> list_C = new ArrayList<Integer>();
for(int i = 0; i <10; i++){
list_C.add((int)(Math.random()*42+1));
}
LinearLayout chartContainer = (LinearLayout) findViewById(R.id.chart_container);
chartContainer.addView(LineChartView.ChartView(MainActivity.this, "Hello", "Count", list_D, list_C));
}
}
LineCharView.class
package com.example.ach;
import java.util.List;
import org.achartengine.ChartFactory;
import org.achartengine.chart.PointStyle;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.model.XYSeries;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYSeriesRenderer;
import android.content.Context;
import android.graphics.Color;
import android.view.View;
public class LineChartView {
private static Context mContext;
/**
*
* @param chartTitle GraphTitle
* @param XYSeries meaning of Series
* @param list_Date X Data
* @param list_Count Y Data
* @return
*/
public static View ChartView(Context context, String chartTitle,
String XYSeries, List<String> list_Date, List<Integer> list_Count) {
LineChartView.mContext = context;
// 資料來源及命名
XYSeries xySeries = new XYSeries(XYSeries);
for(int i=0;i<list_Count.size();i++){
xySeries.add(i+1, list_Count.get(i));
}
// Creating a dataset to hold each series
XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
// Adding Income Series to the dataset
dataset.addSeries(xySeries);
// 線的描述
XYSeriesRenderer xySeriesRenderer = new XYSeriesRenderer();
xySeriesRenderer.setColor(Color.RED);
xySeriesRenderer.setChartValuesTextSize(40);// Value Text Size
xySeriesRenderer.setPointStyle(PointStyle.CIRCLE);
xySeriesRenderer.setFillPoints(true);
xySeriesRenderer.setLineWidth(5);
xySeriesRenderer.setDisplayChartValues(true);
XYMultipleSeriesRenderer multiRenderer = new XYMultipleSeriesRenderer();
multiRenderer.setXLabels(0);
multiRenderer.setChartTitle(chartTitle);
multiRenderer.setChartTitleTextSize(40);
multiRenderer.setXTitle("Date");// X Title
multiRenderer.setYTitle("Count");// Y Title
multiRenderer.setLabelsTextSize(40);// Label Text Size
multiRenderer.setAxisTitleTextSize(40);// Axis Title Text Size
multiRenderer.setZoomButtonsVisible(true);// Zoom?
multiRenderer.setShowGrid(true);// show Grid
for(int i=0; i<list_Date.size(); i++){
multiRenderer.addXTextLabel(i+1, "" + list_Date.get(i).toString());
}
multiRenderer.addSeriesRenderer(xySeriesRenderer);
View mChart = ChartFactory.getLineChartView(mContext, dataset, multiRenderer);
return mChart;
}
}
範例圖示 :
參考資料:MPAndroidChart
參考資料:MPAndroidChart 教程:概述
參考資料 : Android自定义控件 -Canvas绘制折线图(实现动态报表效果)
參考資料 : Android chart tutorial: AChartEngine - Line chart, Bar chart, Range bar
參考資料 : [Andriod] 透過AChartEngine實現BarChart
參考資料 : achartengine之折线图---简单用法
歡迎轉載,請註明出處。
2015年10月21日 星期三
ZigBee-簡介 說明
想投入IOT這塊一定對 : Zigbee 一定不陌生吧!
Zigbee 到底是什麼?
可以吃嗎?
生活中有嗎?
一些阿里不達的問題
.
.
.
.
之前我也思考很久
只知道一大堆的協定和一大堆看不懂的資料
但我只想簡單知道!!!
現在我來簡單的做整理
也會用簡單的圖示來呈現
希望各位能很快的漸入佳境
ZigBee : 一種傳輸協定( 例如 : 藍芽 )
傳輸距離 : 約 50 M
傳輸速率 : 250 kps
耗電 : 5 mA
好處 : 組網
型態 : coordinator 、router、end device
結構 : 樹狀
圖前解說 : 通常 Coordinator 用來接收所有裝置的封包( 有點像 : 頭目角色 )
所以一個族群裡只有一個頭目!
Coordinator 可串 Router 或 End Device
Router 可串 : Router 或 End Device
End Device 不可串接
以下圖示是網路上常看到的
但現在改為顏色,好讓大家比較容易理解
如果看懂以上的圖
我想資訊網所提供的能更快速的理解。
Q&A 1 : 為什麼不 Router 和 End Device 全都接 Coordinator 就好 ?
A : 當然是可以的,但這不是 ZigBee 所樂見的。最終是要佈網才是他的優勢。
Q&A 2 : 如果以現實裝置來說,哪個是 Router? 哪個是 End Device?
A : 這個是好問題,這是由廠商來定義的。但這裡有分辨的小技巧,但還是
以原廠為主,看耗不耗電,如果需要用到插座通常是 Router ; 用電池供電通常
是 End Device 居多。
以上是個人的認知,如有錯誤
本人歡迎接受指教,謝謝大家
參考資料 : WiKi_ZigBee
歡迎轉載,請註明出處。
Zigbee 到底是什麼?
可以吃嗎?
生活中有嗎?
一些阿里不達的問題
.
.
.
.
之前我也思考很久
只知道一大堆的協定和一大堆看不懂的資料
但我只想簡單知道!!!
現在我來簡單的做整理
也會用簡單的圖示來呈現
希望各位能很快的漸入佳境
ZigBee : 一種傳輸協定( 例如 : 藍芽 )
傳輸距離 : 約 50 M
傳輸速率 : 250 kps
耗電 : 5 mA
好處 : 組網
型態 : coordinator 、router、end device
結構 : 樹狀
圖前解說 : 通常 Coordinator 用來接收所有裝置的封包( 有點像 : 頭目角色 )
所以一個族群裡只有一個頭目!
Coordinator 可串 Router 或 End Device
Router 可串 : Router 或 End Device
End Device 不可串接
以下圖示是網路上常看到的
但現在改為顏色,好讓大家比較容易理解
如果看懂以上的圖
我想資訊網所提供的能更快速的理解。
Q&A 1 : 為什麼不 Router 和 End Device 全都接 Coordinator 就好 ?
A : 當然是可以的,但這不是 ZigBee 所樂見的。最終是要佈網才是他的優勢。
Q&A 2 : 如果以現實裝置來說,哪個是 Router? 哪個是 End Device?
A : 這個是好問題,這是由廠商來定義的。但這裡有分辨的小技巧,但還是
以原廠為主,看耗不耗電,如果需要用到插座通常是 Router ; 用電池供電通常
是 End Device 居多。
以上是個人的認知,如有錯誤
本人歡迎接受指教,謝謝大家
參考資料 : WiKi_ZigBee
歡迎轉載,請註明出處。
2015年10月19日 星期一
Android-Appium_腳本_執行順序
寫腳本的過程中
多少一定會有執行的順序
比如 :
1_輸入帳號
2_輸入密碼
3_登入點擊
.
.
.
但是要怎麼寫程式才會乖乖地依序執行
@BeforeTest
@BeforeClass
@BeforeMethod
@testRegisterGateway
@AfterMethod
@AfterMethod
@AfterClass
@AfterTest
2015年10月14日 星期三
2015年10月13日 星期二
Android-360混淆 Application
360 固仕 : 360加固保
各位大大如果完成自己 App 後
如果想上架
但又擔心自己的心血被有心人反組譯
雖然混淆的方法有很多
但是 Dexguard 可以做混淆的動作
如果有第三方的 Jar 在編譯過程容易出錯
今天介紹 360
恩,不錯。
就是 360
這不是打廣告!
這不是打廣告!
這不是打廣告!
先提醒,此方法必須先上傳自己 APK 到 360 官網
等他編譯完再下載
如果真的有個人需求
這可能不符合你
所以真的想好後再去服用!!!
1 . 註冊帳號並且登入
2 . 紅框框
下載應用程式
上傳開發者Apk
下載混淆後Apk
3 . 開啟下載的檔案
注意 : 如有亂碼、空格請更改檔名,不然無法執行檔案。
4 . 將第 2 步處理好的Apk放置相關位置並且輸入 Keystone 相關資訊
完成後就可以安心上架囉。
歡迎轉載,請註明出處。
各位大大如果完成自己 App 後
如果想上架
但又擔心自己的心血被有心人反組譯
雖然混淆的方法有很多
但是 Dexguard 可以做混淆的動作
如果有第三方的 Jar 在編譯過程容易出錯
今天介紹 360
恩,不錯。
就是 360
這不是打廣告!
這不是打廣告!
這不是打廣告!
先提醒,此方法必須先上傳自己 APK 到 360 官網
等他編譯完再下載
如果真的有個人需求
這可能不符合你
所以真的想好後再去服用!!!
1 . 註冊帳號並且登入
2 . 紅框框
下載應用程式
上傳開發者Apk
下載混淆後Apk
3 . 開啟下載的檔案
注意 : 如有亂碼、空格請更改檔名,不然無法執行檔案。
4 . 將第 2 步處理好的Apk放置相關位置並且輸入 Keystone 相關資訊
完成後就可以安心上架囉。
歡迎轉載,請註明出處。
2015年10月12日 星期一
Android-將 Log 寫入文字檔案內
參考資料 : Android Output Write File 輸出 寫入 文件
參考資料 : Android Writing Logs to text File
參考資料 : Android Read Write File Operations – Example
歡迎轉載,請註明出處。
參考資料 : Android Writing Logs to text File
參考資料 : Android Read Write File Operations – Example
歡迎轉載,請註明出處。
2015年10月8日 星期四
Android-AndroidStudio Application 上架
9jUzkHug6OEZ8yNSXcvjEAEAsBSbzLwpDMhdBW1S
YfX66vvdIK3uK6HSf9h7CVL0GQRSIatcZJCuoguv
上架升級
參考資料 : 官方說明_如何產生Key
參考資料 : Android APP 上架流程
參考資料 : Google Play 已發佈的 App 版本升級教學
YfX66vvdIK3uK6HSf9h7CVL0GQRSIatcZJCuoguv
上架升級
參考資料 : 官方說明_如何產生Key
參考資料 : Android APP 上架流程
參考資料 : Google Play 已發佈的 App 版本升級教學
2015年10月7日 星期三
2015年10月6日 星期二
2015年10月1日 星期四
Android-Appium 自動化測試 ( 三 )_Appium(舞台
當我們把腳本的執行檔案寫完後
舞台的特效就要開始做一些小小的設定
1 . 取得裝置序號
注意 : 必須是要打開開發者模式
命令提示字元打
點選右鍵標註( 把序號反白複製 )
2 . 開啟 Appium 點擊 Android 圖示
將要測試的 APK 路徑寫入
選擇要測試的裝置 ( 二選一 )
* : 模擬器測試
將Device Name : MyPhone 輸入在第二框框內
* : 裝置測試
現在將剛剛複製的裝置序號寫在第 2 框框內
3 . 點選設定按鈕
並且將紅色框框內的參數完整的輸入在框框內
4 . 點選右上角執行
等到以下程式 :
就可以等待連接了。
接下來我們可以做什麼 ?
1 . 藉由 Inspector Window 來查看元件屬性。
2 . 執行我們所寫的腳本。
之後全部的流程會在總結。
參考資料 : [Android] Appium 0.18.0 for Windows 新增的 Inspector 如何配置运行?
參考資料 : Android Automation using Appium in Windows
歡迎轉載,請註明出處。
舞台的特效就要開始做一些小小的設定
1 . 取得裝置序號
注意 : 必須是要打開開發者模式
命令提示字元打
adb kill-servier
adb devices
2 . 開啟 Appium 點擊 Android 圖示
將要測試的 APK 路徑寫入
選擇要測試的裝置 ( 二選一 )
* : 模擬器測試
將Device Name : MyPhone 輸入在第二框框內
* : 裝置測試
3 . 點選設定按鈕
並且將紅色框框內的參數完整的輸入在框框內
4 . 點選右上角執行
等到以下程式 :
> info: Console LogLevel: debug
就可以等待連接了。
接下來我們可以做什麼 ?
1 . 藉由 Inspector Window 來查看元件屬性。
2 . 執行我們所寫的腳本。
之後全部的流程會在總結。
參考資料 : [Android] Appium 0.18.0 for Windows 新增的 Inspector 如何配置运行?
參考資料 : Android Automation using Appium in Windows
歡迎轉載,請註明出處。
訂閱:
文章 (Atom)