1.
PRAGMA auto_vacuum = FULL
需在資料庫尚無建立資料時 才可執行
2.執行指令
VACUUM;
2015年12月14日 星期一
2015年9月15日 星期二
android proguard 混淆後 debug
Android SDK下的工具
路徑:android-sdks/tools/proguard/bin/proguardgui.bat
點選左邊選單ReTrace
上方Mapping file 選專案內的 proguard/mapping.txt
將錯誤訊息貼在 Obfuscated stack trace
最後按下右下方的 ReTrace
將錯誤訊息貼在 Obfuscated stack trace
最後按下右下方的 ReTrace
2015年9月14日 星期一
Java Robot 滑鼠控制
Robot類別提供以下幾個方法來模擬滑鼠動作:
public void mouseMove(int x, int y); // 螢幕位置
/*java.awt.event.InputEvent.BUTTON1_MASK 代表左鍵
* java.awt.event.InputEvent.BUTTON2_MASK 代表中鍵
* java.awt.event.InputEvent.BUTTON3_MASK 代表右鍵*/
public void mousePress(int buttons);
public void mouseRelease(int buttons); //同上
/* 滾輪的轉動量 正值為向前轉,負值為向後轉。*/
public void mouseWheel(int wheelAmt);
詳細API
http://docs.oracle.com/javase/7/docs/api/java/awt/Robot.html
public void mouseMove(int x, int y); // 螢幕位置
/*java.awt.event.InputEvent.BUTTON1_MASK 代表左鍵
* java.awt.event.InputEvent.BUTTON2_MASK 代表中鍵
* java.awt.event.InputEvent.BUTTON3_MASK 代表右鍵*/
public void mousePress(int buttons);
public void mouseRelease(int buttons); //同上
/* 滾輪的轉動量 正值為向前轉,負值為向後轉。*/
public void mouseWheel(int wheelAmt);
詳細API
http://docs.oracle.com/javase/7/docs/api/java/awt/Robot.html
2015年8月26日 星期三
Android 修改系統時間
需先Root後才可使用
public static boolean changeSystemTime(String datetime) {
String[] times = datetime.split(" ");
if (times.length == 2) {
return changeSystemTime(times[0].replace("-", ""),
times[1].replace(":", ""));
}
return false;
}
private static boolean changeSystemTime(String date, String time) {
try {
Process process = Runtime.getRuntime().exec("su");
DataOutputStream os = new DataOutputStream(
process.getOutputStream());
String command = "date -s " + date + "." + time + "\n";
os.writeBytes(command);
os.flush();
os.writeBytes("exit\n");
os.flush();
process.waitFor();
return true;
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
public static boolean changeSystemTime(String datetime) {
String[] times = datetime.split(" ");
if (times.length == 2) {
return changeSystemTime(times[0].replace("-", ""),
times[1].replace(":", ""));
}
return false;
}
private static boolean changeSystemTime(String date, String time) {
try {
Process process = Runtime.getRuntime().exec("su");
DataOutputStream os = new DataOutputStream(
process.getOutputStream());
String command = "date -s " + date + "." + time + "\n";
os.writeBytes(command);
os.flush();
os.writeBytes("exit\n");
os.flush();
process.waitFor();
return true;
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
2015年8月24日 星期一
eclipse android 加快開啟速度
1. 在 Windows -> Preferences -> Validation,按一下「Disable All」就可以把所有的驗證器都關掉。之後你可以在編輯器中按右鍵,在選單中選擇「Validate」來手動驗證。
2.在 Windows -> Preferences -> General -> Startup and Shutdown
3.到Eclipse的目錄下找到eclipse.ini 檔,在修改以下參數前請先複製一份。
白色為不需修改部分,根據不同版本的eclipse會不太一樣
紅色為須自己加入的參數
2.在 Windows -> Preferences -> General -> Startup and Shutdown
- Marketplace Client:eclipse 廣告更新
- Equinox Provisioning Platform Automatic Update Support:eclipse 自動更新
- mylyn:用在任務管理
- WindowBuilder Discovery UI:Java 拉UI用的
- Codan Analysis UI for C/C++:C/C++ 做UI用
3.到Eclipse的目錄下找到eclipse.ini 檔,在修改以下參數前請先複製一份。
白色為不需修改部分,根據不同版本的eclipse會不太一樣
紅色為須自己加入的參數
-startup plugins/org.eclipse.equinox.launcher_1.3.0.v20120522-1813.jar --launcher.library plugins/org.eclipse.equinox.launcher.win32.win32.x86_1.1.200.v20120913-144807 -product org.eclipse.epp.package.java.product --launcher.defaultAction openFile --launcher.XXMaxPermSize 1024M -showsplash org.eclipse.platform --launcher.XXMaxPermSize 1024m --launcher.defaultAction openFile -vmargs -server -Dosgi.requiredJavaVersion=1.7 -Dhelp.lucene.tokenizer=standard -Xverify:none -Xmn128m -Xms1024m -Xmx1024m -Xss2m -XX:PermSize=128m -XX:MaxPermSize=128m -XX:+UseParallelGC儲存後重開eclipse
2015年8月17日 星期一
Google Cloud Messaging(GCM)
Eclipse
例專案package是com.griever.test
例專案package是com.griever.test
在AndroidManifest加入以下內容
加入權限
<permission
android:name="com.griever.test.permission.C2D_MESSAGE"
android:protectionLevel="signature"/>
<uses-permission android:name="com.griever.test.permission.C2D_MESSAGE"/>
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/>
<uses-permission android:name="android.permission.INTERNET" />
<receiver
android:name="com.griever.test.gcm.GCMBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.griever.test" />
</intent-filter>
</receiver>
<service android:name="com.griever.test.gcm.GCMIntentService" />
public class GCMBroadcastReceiver extends BroadcastReceiver {
final String TAG = "GCM";
public void onReceive(Context context, Intent intent) {
Log.v(TAG, "onReceive: " + intent.getAction());
ComponentName comp = new ComponentName(context.getPackageName(),
GCMIntentService.class.getName());
context.startService(intent.setComponent(comp));
setResultCode(Activity.RESULT_OK);
}
public class GCMIntentService extends GCMBaseIntentService {@SuppressWarnings("hiding")
private static final String TAG = "GCMIntentService";
private static final String GOOGLE_PROJECT_ID = "12345678910";
public GCMIntentService() {
super(GOOGLE_PROJECT_ID);
}
@Override
protected void onRegistered(Context context, String registrationId) {
ServerUtilities.register(context, registrationId);
}
@Override
protected void onUnregistered(Context context, String registrationId) {
if (GCMRegistrar.isRegisteredOnServer(context)) {
ServerUtilities.unregister(context, registrationId);
} else {
// This callback results from the call to unregister made on
// ServerUtilities when the registration to the server failed.
// Log.i(TAG, "Ignoring unregister callback");
}
}
@Override
protected void onMessage(Context context, Intent intent) {
//接收訊息
}
}
@Override
protected void onDeletedMessages(Context context, int total) {
// Log.i(TAG, "Received deleted messages notification");
}
@Override
public void onError(Context context, String errorId) {
// Log.i(TAG, "Received error: " + errorId);
}
@Override
protected boolean onRecoverableError(Context context, String errorId) {
// Log.i(TAG, "Received recoverable error: " + errorId);
return super.onRecoverableError(context, errorId);
}
}新增ServerUtilities.java
public final class ServerUtilities {
private static final int MAX_ATTEMPTS = 5;
private static final int BACKOFF_MILLI_SECONDS = 2000;
private static final Random random = new Random();
private static final String TAG = "ServerUtilities";
static boolean register(final Context context, final String regId) {
String serverUrl = "http://192.168.1.100/gcm_register";
Map<String, String> params = new HashMap<String, String>();
params.put("regId", regId);
long backoff = BACKOFF_MILLI_SECONDS;
for (int i = 1; i <= MAX_ATTEMPTS; i++) {
// Log.d(TAG, "Attempt #" + i + " to register");
try {
post(serverUrl, params);
GCMRegistrar.setRegisteredOnServer(context, true);
return true;
} catch (Exception e) {
Log.e(TAG, "Failed to register on attempt " + i, e);
if (i == MAX_ATTEMPTS) {
break;
}
try {
Thread.sleep(backoff);
} catch (InterruptedException e1) {
Thread.currentThread().interrupt();
return false;
}
backoff *= 2;
}
}
return false;
}
static void unregister(final Context context, final String regId) {
String serverUrl = "http://192.168.1.100//gcm_unregister";
Map<String, String> params = new HashMap<String, String>();
params.put("regId", regId);
try {
post(serverUrl, params);
GCMRegistrar.setRegisteredOnServer(context, false);
// Log.i(TAG, "server_unregistered device OK");
} catch (Exception e) {
Log.i(TAG, "server_unregistered device error");
}
}
private static void post(String endpoint, Map<String, String> params)
throws IOException {
URL url;
try {
url = new URL(endpoint);
} catch (MalformedURLException e) {
throw new IllegalArgumentException("invalid url: ");
}
StringBuilder bodyBuilder = new StringBuilder();
Iterator<Entry<String, String>> iterator = params.entrySet().iterator();
// constructs the POST body using the parameters
while (iterator.hasNext()) {
Entry<String, String> param = iterator.next();
bodyBuilder.append(param.getKey()).append('=')
.append(param.getValue());
if (iterator.hasNext()) {
bodyBuilder.append('&');
}
}
String body = bodyBuilder.toString();
// Log.v(TAG, "Posting '" + body + "' to " + url);
byte[] bytes = body.getBytes();
HttpURLConnection conn = null;
try {
conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
conn.setFixedLengthStreamingMode(bytes.length);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded;charset=UTF-8");
// post the request
OutputStream out = conn.getOutputStream();
out.write(bytes);
out.close();
// handle the response
int status = conn.getResponseCode();
if (status != 200) {
throw new IOException("Post failed with error code " + status);
}
InputStream is = conn.getInputStream();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
String line;
StringBuffer response = new StringBuffer();
while ((line = rd.readLine()) != null) {
response.append(line);
}
rd.close();
// Log.e(TAG, "return :" + response.toString() + " "
// + response.toString().equals("OK"));
if (!response.toString().equals("OK")) {
throw new IOException("Post failed with error msg ");
}
} finally {
if (conn != null) {
conn.disconnect();
}
}
}
}
加入以下程式碼註冊gcm
GCMRegistrar.checkDevice(mContext);
GCMRegistrar.checkManifest(mContext);
final String regId = GCMRegistrar.getRegistrationId(mContext);
if (regId.equals("")) { GCMRegistrar.register(mContext, CommonUtilities.SENDER_ID);
} else { System.out.println("gcm is already regist"); // GCMRegistrar.unregister(mContext); // if (GCMRegistrar.isRegisteredOnServer(mContext)) { // } else { // }
}
2015年7月14日 星期二
2015年7月10日 星期五
android surfaceview 相關
CustomView extends SurfaceView implements Callback
private SurfaceHolder sfh;
private Paint mPaint;
private Paint mClearPaint;
private CoreThread coreThread;//
//surfaceview 透明背景
setZOrderOnTop(true);
sfh = getHolder();
sfh.addCallback(this);
sfh.setFormat(PixelFormat.RGBA_8888);
//畫筆設定
mPaint = new Paint();
mPaint.setAntiAlias(true);
mClearPaint = new Paint();
mClearPaint.setXfermode(new PorterDuffXfermode(Mode.CLEAR));
//畫面重整
private void draw() {
Canvas canvas = null;
try {
canvas = sfh.lockCanvas();
if (canvas != null) {
canvas.drawPaint(mClearPaint);
if (MainSprite != null) {
drawMainSprite(canvas);
}
synchronized (drawLock) {
for (SpriteParam sp : FoodList) {
drawFoodSprite(canvas, sp);
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (canvas != null)
sfh.unlockCanvasAndPost(canvas);
}
}
private SurfaceHolder sfh;
private Paint mPaint;
private Paint mClearPaint;
private CoreThread coreThread;//
//surfaceview 透明背景
setZOrderOnTop(true);
sfh = getHolder();
sfh.addCallback(this);
sfh.setFormat(PixelFormat.RGBA_8888);
//畫筆設定
mPaint = new Paint();
mPaint.setAntiAlias(true);
mClearPaint = new Paint();
mClearPaint.setXfermode(new PorterDuffXfermode(Mode.CLEAR));
//畫面重整
private void draw() {
Canvas canvas = null;
try {
canvas = sfh.lockCanvas();
if (canvas != null) {
canvas.drawPaint(mClearPaint);
if (MainSprite != null) {
drawMainSprite(canvas);
}
synchronized (drawLock) {
for (SpriteParam sp : FoodList) {
drawFoodSprite(canvas, sp);
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (canvas != null)
sfh.unlockCanvasAndPost(canvas);
}
}
2015年6月28日 星期日
android timepicker 設定分間隔
@SuppressLint("NewApi")
private void setTimePickerInterval(TimePicker timePicker) {
try {
Class<?> classForid = Class.forName("com.android.internal.R$id");
// Field timePickerField = classForid.getField("timePicker");
Field field = classForid.getField("minute");
NumberPicker minutePicker = (NumberPicker) timePicker
.findViewById(field.getInt(null));
minutePicker.setMinValue(0);//最小0
minutePicker.setMaxValue(1);//最大1
List<String> displayedValues = new ArrayList<String>();
for (int i = 0; i < 60; i += 30) {//30分為單位
displayedValues.add(String.format("%02d", i));
}
for (int i = 0; i < 60; i += 30) {//30分為單位
displayedValues.add(String.format("%02d", i));
}
minutePicker.setDisplayedValues(displayedValues
.toArray(new String[0]));
} catch (Exception e) {
e.printStackTrace();
}
}
private void setTimePickerInterval(TimePicker timePicker) {
try {
Class<?> classForid = Class.forName("com.android.internal.R$id");
// Field timePickerField = classForid.getField("timePicker");
Field field = classForid.getField("minute");
NumberPicker minutePicker = (NumberPicker) timePicker
.findViewById(field.getInt(null));
minutePicker.setMinValue(0);//最小0
minutePicker.setMaxValue(1);//最大1
List<String> displayedValues = new ArrayList<String>();
for (int i = 0; i < 60; i += 30) {//30分為單位
displayedValues.add(String.format("%02d", i));
}
for (int i = 0; i < 60; i += 30) {//30分為單位
displayedValues.add(String.format("%02d", i));
}
minutePicker.setDisplayedValues(displayedValues
.toArray(new String[0]));
} catch (Exception e) {
e.printStackTrace();
}
}
2015年6月17日 星期三
android EditText 取消軟鍵盤自動彈出
Activity
Xml
或
Dialog
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
Xml
<activity android:name="org.MainActivity" android:label="@string/app_name" android:windowSoftInputMode="stateHidden" />
或
Dialog
AlertDialog dialog = new AlertDialog.Builder(this).setView(editText).create(); dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); dialog.show();
2015年4月26日 星期日
Android ProGuard 加入第三方包
Android ProGuard混淆打包有第三方jar包的時候混淆配置文件的書寫
-dontwarn com.xx.bbb.** ##第三方jar包的包名不警告找不到引用
-keep class com.xx.bbb.** { *;} ##第三方jar包的包名不混淆
-dontwarn com.xx.bbb.** ##第三方jar包的包名不警告找不到引用
-keep class com.xx.bbb.** { *;} ##第三方jar包的包名不混淆
2015年4月23日 星期四
android 同Activity下 設定不同fragment 翻轉
Override
setUserVisibleHint()
in each fragment.
In the portrait only fragments:
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if(isVisibleToUser) {
Activity a = getActivity();
if(a != null) a.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
}
in the the portrait/landscape fragment:
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if(isVisibleToUser) {
Activity a = getActivity();
if(a != null) a.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
}
}
This will allow the whole activity to rotate in one fragment, but fix it to portrait in others.
2015年4月20日 星期一
Java 字串 Unicode \u 顯示
public static String escapeUnicode(String input) {
StringBuilder b = new StringBuilder(input.length());
Formatter f = new Formatter(b);
for (char c : input.toCharArray()) {
if (c < 128) {
b.append(c);
} else {
f.format("\\u%04x", (int) c);
}
}
return b.toString();
}
2015年3月6日 星期五
android 9-patch image programmatically
private Drawable getThumb(int resId) {
Bitmap b = GBitmap.getResSoftBitmap(mContext, resId);
byte[] chunk = b.getNinePatchChunk();
NinePatchDrawable mapNinePatch = new NinePatchDrawable(getResources(),
b, chunk, new Rect(), null);
return mapNinePatch;
}
Bitmap b = GBitmap.getResSoftBitmap(mContext, resId);
byte[] chunk = b.getNinePatchChunk();
NinePatchDrawable mapNinePatch = new NinePatchDrawable(getResources(),
b, chunk, new Rect(), null);
return mapNinePatch;
}
android EditText 光標顏色 全選字
EditText光標的顏色設定
xml
android:textCursorDrawable="@null"
程式碼
try {
Field f = TextView.class.getDeclaredField("mCursorDrawableRes");
f.setAccessible(true);
f.set(yourEditText, R.drawable.cursor);
} catch (Exception ignored) {
}
全選EditText裡的字
editText.setSelection(0, length);
editText.setSelection(0);
editText.setSelectAllOnFocus(true);
xml
android:textCursorDrawable="@null"
程式碼
try {
Field f = TextView.class.getDeclaredField("mCursorDrawableRes");
f.setAccessible(true);
f.set(yourEditText, R.drawable.cursor);
} catch (Exception ignored) {
}
全選EditText裡的字
editText.setSelection(0, length);
editText.setSelection(0);
editText.setSelectAllOnFocus(true);
2015年2月9日 星期一
android ListView selector或OnItemClickListener 沒反應
ListView
Selector或OnItemClickListener 沒反應
確認在Adapter裡的Layout是否有Button或View設定OnClick
請設定obj_v.setFocusable(false);
Selector或OnItemClickListener 沒反應
確認在Adapter裡的Layout是否有Button或View設定OnClick
請設定obj_v.setFocusable(false);
訂閱:
文章 (Atom)