2015年12月14日 星期一

sqlite 刪除資料後 檔案沒變小

1.
PRAGMA auto_vacuum = FULL

需在資料庫尚無建立資料時 才可執行

2.執行指令
VACUUM;

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

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

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;
}

2015年8月24日 星期一

eclipse android 加快開啟速度

1. 在 Windows -> Preferences -> Validation,按一下「Disable All」就可以把所有的驗證器都關掉。之後你可以在編輯器中按右鍵,在選單中選擇「Validate」來手動驗證。

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用
以上幾個沒用到的都可以取消勾選,Android Development Toolkit 做Android 開發要打勾。

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
gcm.jar 加入專案的libs

在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" />


加在application內

<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" />



新增GCMBroadcastReceiver.java

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);
}


新增GCMIntentService.java

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);
}
}



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();
}
}

2015年6月17日 星期三

android EditText 取消軟鍵盤自動彈出

Activity

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包的包名不混淆

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;
}

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);

2015年2月9日 星期一

android ListView selector或OnItemClickListener 沒反應

ListView

Selector或OnItemClickListener 沒反應

確認在Adapter裡的Layout是否有Button或View設定OnClick

請設定obj_v.setFocusable(false);