2016年4月22日 星期五

架設內部網路(Intranet)

架設內部網路的需求因人而異,這次因為要去別的地方展示App系統,而系統有一部分是有使用網頁,所以會把APServer一起帶到要展示系統的環境,並把網路架成內部網路而不是外部網路(internet)才能隨時處理突發狀況,以下是內部網路的架設過程,使用的硬體有型號ASUS RT-N53AP一台筆電和一支手機

Step 1: AP與筆電用網路線連接,注意AP的插孔,一般如果要與電信公司的數據機連接的話,會插比較特別的那個插口(此圖是深藍色的口),這邊是插黃色的插口。
 

Step 2: 接著開啟瀏覽器,在網址列輸入設定AP的私人IP,每家廠商的AP會有不同登入IP,登入IP通常會寫在說明書或AP機盒上,此範例是192.168.1.1,然後輸入廠商預設的帳號密碼,登入後即可看到以下畫面。

Step 3: 頁籤切換到DHCP伺服器,看到IP Pool起始位址與結束位址,這兩個的區間從192.168.1.2192.168.1.254總共有253個位址,表示可以提供給253台裝置在同一個內部網域內,但要注意AP是否能乘載那麼多台裝置同時連線。

Step 4: 設定無線網路,讓裝置可以無線連接AP,基本的設定是SSIDWPA-PSK金鑰。

Step 5: 以上AP設定完成後,開始設定筆電的網路,將資料夾路徑切換到>控制台\網路和網際網路\網路連線,對乙太網路點右鍵,選內容,會出現step 6畫面。
 

Step 6: 選擇TCP/IPv4按確定,進入Step 7畫面。

Step 7: 選擇使用下列的IP位址(S)”選項,IP位址輸入step 3設定的區間裡其中一個IP,此範例為192.168.1.2,子網路遮罩會自動填入,預設閘道不用設定,設定完成後按確定。

Step 8: 上述設定完成後,換手機設定IP,因為AP有設定DHCP(自動分配IP),所以不用自己手動設定。若要手動設定可參考紅色字體。

*P.S., 換設定手機的IP,點"設定"->"Wi-Fi"->連線到Step 4設定的SSID名稱,此範例為intranet,連到後按住該SSID名稱不放,會跳出如下畫面,選擇Modify network,畫面會換到Step 9

Step 9: ”Show advanced options”選項打勾,IPv4 settings選擇static(靜態)IPv4 address欄位跟Step 7一樣,輸入一組IP,此範例為192.168.1.4,但要注意不可以重複目前已有在使用的IP,例如:前面筆電設定的IP192.168.1.2,這邊就不可以再設一樣的IP。接著設定Gateway(預設閘道)IP,這邊的IP是使用登入時AP所輸入的IP,設定完成後按save

Step 10: AP、筆電和手機都設定完成後,接著讓筆電去ping手機的IP,若成功,換手機ping筆電IP,若兩邊可以互相ping成功,表示剛設定的內部網路成功了。首先先在筆電上開啟命令提示字元輸入ping 192.168.1.4,若成功會看到以下畫面,接著換手機ping筆電,在此之前要先下載可以ping IPApp,此範例用的AppPing&DNS,該App ping筆電成功的畫面如最後一張圖。以上就是整個內部網路的設定過程。


此篇文章word檔

2016年4月14日 星期四

[Android] AlertDialog 功能,符合條件才消失



在使用AlertDialog功能之前,要先import AlertDialog的函式庫,如果有使用到其他元件也要import,像這裡也有用到EditText,所以也要import
import android.support.v7.app.AlertDialog;
import android.widget.EditText;
在onCreate(Bundle savedInstanceState)方法或自定義的方法內宣告AlertDialog
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
        EditText editText = new EditText(MainActivity.this);
        builder.setTitle("Please enter your Student ID");
        builder.setView(editText);
     //按到旁邊的空白處AlertDialog也不會消失
        builder.setCancelable(false);
        //註冊AlertDialog的按鈕,按下去之後發生的事件
        builder.setPositiveButton("OK", altDlgOnClkPosiBtnLis);
        builder.show();
}

private DialogInterface.OnClickListener altDlgOnClkPosiBtnLis = new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            //如果EditText是空值,AlertDialog就必須一直出現,否則執行else的程式
            if ("".equals(editText.getText().toString().trim())) { 
                //讓AlertDialog一直出現,我的方法是先把原本的AlertDialog所佔的資源釋放掉,再重新宣告一次.
                dialog.dismiss();

                builder = new AlertDialog.Builder(MainActivity.this);
                editText = new EditText(MainActivity.this);
                builder.setTitle("Please enter your Student ID");
                builder.setView(editText);
                builder.setCancelable(false);
                builder.setPositiveButton("OK", altDlgOnClkPosiBtnLis);
                builder.show();
            }else{
                //To do something else.
            }
        }
}

[Android] How-to read/write files in Android

最近要試著把儲存在Android系統手機裡面的Sqlite資料庫檔案抓出來,看儲存在裡面的資料,但因為Android系統會把自己開發的專案App檔案都放在Android系統的最內層,因此必須取得最高權限(Root)才能存取這些檔案,可是在嘗試過ADB、解除Root等方式後,還是無法取得Sqlite檔案,所以找到下面這篇詳細的文章,使用這篇文章最後一段的Read/Write to publicly readable files的方法,將資料存到記事本,然後從手機的DOWNLOAD (DIRECTORY_DOWNLOADS) 資料夾內把記事本抓出來,分析裡面儲存的資料

Read from res directory
If your application requires external file resources, you can include them in your distribution package by placing them in the res/raw folder of your project hierarchy.
To access these read-only file resources, call the openRawResource method from your application’s Resource object to receive an InputStream based on the specified file. Pass in the filename (without the extension) as the variable name from the R.raw class, as shown in the following code
Resources r = getResources();
InputStream file = r.openRawResource(R.raw.filename);

Read from assets directory
Android offers one more directory where you can keep files which also will be included in package. This directory called /assets. There are some difference from res directory.
With resources, there's built-in support for providing alternatives for different languages, OS versions, screen orientations, etc., as described here. None of that is available with assets. Also, many parts of the API support the use of resource identifiers. Finally, the names of the resources are turned into constant field names that are checked at compile time, so there's less of an opportunity for mismatches between the code and the resources themselves. None of that applies to assets.source
Context context = getApplicationContext();
InputStream is = context.getAssets().open(filename);
String text = "";

int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
is.close();
text = new String(buffer);

Read/Write to Internal Storage
Internal storage refers to the hard drive on device. Internal storage gives you the ability to prevent other applications from accessing the files you save and are tied directly to your app.
Files stored in /data/data/packagename/files/filename.txt. There are few modes for file access
  • MODE_PRIVATE - create a new file or overwrite one if it already exists with the same name
  • MODE_APPEND - create the file if it doesn’t exist and allow you to append to the file if it does exist
  • MODE_WORLD_READABLE - file is readable by any other application
  • MODE_WORLD_WRITEABLE - file is writeable by any other application
Write to file in internal storage
String FILE_NAME = "file.txt";
try {
    FileOutputStream fos = openFileOutput(FILE_NAME, Context.MODE_PRIVATE);
    fos.write(someText.toString().getBytes());
    fos.close();
} catch (Exception e) {
    e.printStackTrace();
}
Read from file in internal storage
try {
    BufferedReader bReader = new BufferedReader(new InputStreamReader(openFileInput(FILE_NAME)));
    String line;
    StringBuffer text = new StringBuffer();                
    while ((line = bReader.readLine()) != null) {
        text.append(line + "\n");
    }
} catch (IOException e) {
    e.printStackTrace();
}

Read/Write to SDCard
External storage is typically either a removable storage media (i.e. SD Card) or an internal non-removable storage that is accessed in the same manner.
The most important thing to remember when storing files on external storage is that no security is enforced on files stored here. Any application can access, overwrite, or delete files stored on the external storage.
In order to write data to SDCard, the application need permission WRITE_EXTERNAL_STORAGE, which can be specified in the file AndroidManifest.xml.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Check external storage
private static boolean isExternalStorageReadOnly() {
    String extStorageState = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(extStorageState)) {
        return true;
    }
    return false;
}

private static boolean isExternalStorageAvailable() {
    String extStorageState = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED.equals(extStorageState)) {
        return true;
    }
    return false;
}
Write to SDCard
String FILE_NAME = "file.txt";
if (isExternalStorageAvailable() && isExternalStorageReadOnly()) {
    String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath();
    File file = new File(baseDir, FILE_NAME);
    FileWriter writer = null;
    try {
        writer = new FileWriter(file);
        writer.write(text.toString());
        writer.close();
    } catch (IOException e) {
        e.printStackTrace();
    }    
}
Read from SDCard
String FILE_NAME = "file.txt";
if (isExternalStorageAvailable() && isExternalStorageReadOnly()) {
    String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath();
    File file = new File(baseDir, FILE_NAME);

    String line = "";
    StringBuilder text = new StringBuilder();

    try {
        FileReader fReader = new FileReader(file);
        BufferedReader bReader = new BufferedReader(fReader);

        while( (line = bReader.readLine()) != null  ){
            text.append(line+"\n");
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Read/Write to Cache
Should your application need to cache temporary files, Android offers both a managed internal cache, and (since Android API level 8) an unmanaged external cache. You can access them by calling the getCacheDirand getExternalCacheDir methods, respectively, from the current Context.
Files stored in either cache location will be erased when the application is uninstalled. Files stored in the internal cache will potentially be erased by the system when it is running low on available storage; files stored on the external cache will not be erased, as the system does not track available storage on external media.
Read from cache dir
String TMP_FILE_NAME = "tmp_file.txt";
File tmpFile;

File cacheDir = getBaseContext().getCacheDir();
tmpFile = new File(cacheDir.getPath() + "/" + TMP_FILE_NAME) ;

String line="";
StringBuilder text = new StringBuilder();

try {
    FileReader fReader = new FileReader(tmpFile);
    BufferedReader bReader = new BufferedReader(fReader);

    while( (line=bReader.readLine()) != null  ){
        text.append(line+"\n");
    }
} catch (FileNotFoundException e) {
    e.printStackTrace();
}catch(IOException e){
    e.printStackTrace();
}
Write to cache dir
FileWriter writer = null;
try {
    writer = new FileWriter(tmpFile);
    writer.write(text.toString());
    writer.close();

    // path to file
    // tmpFile.getPath() 

} catch (IOException e) {
    e.printStackTrace();
}

Read/Write to publicly readable files
Android 2.2 (API level 8) includes a convenience method, Environment.getExternalStoragePublicDirectory, that can be used to find a path in which to store your application files. The returned location is where users will typically place and manage their own files of each type. This is particularly useful for applications that provide functionality that replaces or augments system applications, such as the camera, that store files in standard locations.
The getExternalStoragePublicDirectory method accepts a string parameter that determines which subdirectory you want to access using a series of Environment static constants:
  • DIRECTORY_DCIM - pictures and videos taken by the device
  • DIRECTORY_DOWNLOADS - files downloaded by the user
  • DIRECTORY_MOVIES — movies
  • DIRECTORY_MUSIC — audio fi les that represent music
  • DIRECTORY_PICTURES — pictures
Note that if the returned directory doesn’t exit, you must create it before writing fi les to the directory, as shown in the following snippet
String IMAGE_FILE_NAME = "image.png";
File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File file = new File(path, FILE_NAME);
try {
    path.mkdirs();
    // statements for file store
} catch (IOException e) {
    Log.d(TAG, "Error writing " + IMAGE_FILE_NAME, e);
}

*apk存放位置 C:\Users\nschenoffice\AndroidStudioProjects\Communication2-v3\app\build\outputs\apk
*That is not possible at runtime. Resources and assets are read-only at runtime.
Cite : http://en.proft.me/2014/06/21/how-readwrite-files-android/

[WPF] 文章中搜尋某特定字串

using System.Text.RegularExpressions;

public partial class MainWindow : Window
{
    public void SearchString()
    {
        Match match = Regex.Match("要被搜尋的文章", "指定要尋找的字串", RegexOptions.IgnoreCase);
        // Here we check the Match instance.
        if (match.Success)
        {
            //將文字反白
            tb_article.Select(match.Index, match.Length);
        }   

        //滑鼠選取的字串給a變數
        sting a = tb_article.SelectedText;
    }
}
//在.xaml檔裡設定textbox屬性,可以完成複製和貼上多行的功能
<textbox acceptsreturn="True" x:name="tb_article"></textbox>
tb_article為TextBox

2016年4月1日 星期五

[Android] 使用SharedPreferences紀錄闖關進度

SharedPreferences適合用來記錄小量資料的方法,主要是用xml檔來記錄數值,在記錄數值之前不需要先建立檔案,這個方法在儲存資料時如果找不到檔案會自動新增一個xml檔.

在下圖的程式碼主要列出該方法的讀取資料與儲存資料的功能,儲存跟更新資料是使用同一個函數,需要注意的是:
1. SharedPreferences要宣告在onCreate()方法區塊內,否則會出現找不到參考物件的錯誤.
2. 如果要在不同的Activity頁面讀取同一筆資料,要在每個頁面連結的.java檔內都宣告SharedPreferences,然後一樣使用getInt("資料名稱",0)取出資料,"0"表示找不到該筆資料就預設回傳0.

[Android] Activity 頁面的切換(能夠返回前一個頁面)

這篇文章要記錄按下Button之後可以跳到下一個頁面,並且按下Android的返回鍵(Home鍵左邊那個)可以回到前一個頁面.

以此圖片範例作為講解,首先在activity_main.xml新增一個Button,接著新增第二個Activity頁面,File->Activity->Empty Activity.

輸入Activity Name按下Finish.



按下Finish之後,會看到layout資料夾下自動新增使用者介面的.xml檔.



AndroidManifest.xml也自動增加程式碼將使用者介面和程式商業邏輯連起來.

接著在MainActivity.java(這個檔案與有Button元件的activity_main.xml連接),輸入觸發Button 按下後的事件程式碼. 參考圖檔.

其中的程式碼使用到Intent這個物件,來切換頁面,如此一來當按下返回鍵時才能回到前一頁,如果直接在Button的onClick屬性增加方法是無法返回的,而Bundle物件可以將當前頁面的參數值傳到下一個頁面.
//建立Intent並指定要去Main2Activity的頁面final 
Intent intent = new Intent(this, Main2Activity.class);
//建立Bundle儲存要傳送的資料
final Bundle bundle = new Bundle();

結果:

Android 功能紀錄 (顯示訊息, 禁止螢幕翻轉, 消除ImageView兩邊空白, TextView加底線)

顯示訊息(Toast提示功能)
Toast.makeText(MainActivity.this, "string", Toast.LENGTH_SHORT).show();
第一個為Context物件,MainActivity.this代表Activity物件,可以傳入是因為ContextActivity父類別.
第二個參數為要顯示的字串.
第三個參數是Toast顯示時間.

禁止螢幕翻轉
打開manifests資料夾下的AndroidManifest.xml檔案,在<activity></activity>中,加入
android:screenOrientation="portrait" (強制直向) 或 android:screenOrient style="background-color: white;ation="landscape" (強制橫向).

消除ImageView兩邊空白

打開宣告ImageView元件的xml檔,在ImageView屬性的地方加入android:adjustViewBounds="true" ,如下範例:
<ImageView android:layout_width="wrap_content"    
           android:layout_height="wrap_content"    
           android:id="@+id/imageView100"    
           android:adjustViewBounds="true" />
TextView加底線
打開資料夾res/values/strings.xml檔案,在要加入底線的文字兩邊加<u>some  text</u>如下範例:
<string name="name"><u>some text</u></string>
或在程式碼輸入:
result.setText(Html.fromHtml("<u>"+getResources().getString(R.string.name)+"</u>"));
result為TextView元件的名稱

[Android] 程式資源歸類和使用

使用文字檔案: file path : res -> values -> strings.xml
假設strings.xml檔案內儲存著下列文字定義
<string name=”text_btSubmit”>Submit</string>
l   透過XML取得:
<Button android:layout_width=”fill_parent”
        android:layout_height=”wrap_content”
        android:text=”@string/text_btSubmit”/>
l   透過程式碼取得:
Button btSubmit = (Button)findViewByid(R.id.btSubmit);
btSubmit.setText(R.string.text_btSubmit);
使用圖形檔案: file path : res -> drawable
假設res/drawable目錄內儲存著icon.png
l   透過XML取得:
<ImageView android:layout_width="wrap_content"
           android:layout_height=”wrap_content”
           android:src=”@drawable/icon”/>
l   透過程式碼取得:
ImageView imageView = (ImageView)findViewById(R.id.imageView);
imageView.setImageResource(R.drawable.icon);
使用影音檔案: file path : res -> raw
假設res/raw資料夾下有一個apple.mp3的檔案
l   透過程式碼取得:
MediaPlayer mp = MediaPlayer.create(類別名稱, R.raw.apple);
mp.start();
使用layout檔案: file path : res -> layout
假設res/layout目錄內儲存著main_activity.xml檔案
l   透過程式碼讓.java檔和.xml使用者介面檔連結:
setContentView(R.layout.main_activity);

@+id@id @android:id 差別

@+id : 表示新增一個 id
@id : 參考一個已經存在的 id,沒有指定 namespace 表示為目前應用程式自行定義的 id
@android:id : 參考一個已經存在的 id,且其 namespace android,可以在 android-sdk\platforms\android-8\data\res\values\ids.xml 裡看到所有 Android 預先定義的 id

[引用]
http://cw1057.blogspot.tw/2011/04/android-idid-androidid.html
書籍: Android 5.X App開發教戰手冊

Android Studio 介面基本設定和快捷鍵使用

顯示程式行號File -> Settings -> Editor -> Appearance -> Show line numbers 打勾



程式自動排版 : Ctrl + Alt + L

介面背景顏色 : Appearance -> Theme (option items)

檔案重新命名 : 先點要修改名稱的檔案 -> Shift + F6