show code block

2017年4月26日 星期三

Android元件(DisplayMetrics) ─ 螢幕大小、解析度獲取

前言:


Android有別於ios每一台螢幕的解析度大小都不一樣,再加入平板類的更是零零總總。

當你一個東西想要調整圖片大小,其實可以利用這個和Bitmap的結合來做。






實作:

xml中間的TextView給個id就完成了。
main_activity.xml

<?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"
    tools:context="com.spinner.a015865.displaymetrics.MainActivity">

    <TextView
        android:id="@+id/text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:gravity="center"
        android:text="Hello World!"
        android:textSize="20dp" />
</RelativeLayout>




MainActivity.java
public class MainActivity extends AppCompatActivity {

    private TextView mTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTextView = (TextView) findViewById(R.id.text_view);
        DisplayMetrics displayMetricss = getResources().getDisplayMetrics();

        DisplayMetrics displayMetrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
        mTextView.setText("您的解析度:" + displayMetricss.widthPixels
                + "*" + displayMetricss.heightPixels);
    }
}






後記:就不提供Demo了,造上面做一定出的來,有問題再說吧。

2017年4月20日 星期四

third-party元件(XZing.core) ─ 生成QRCode、導入第三方(jar)

前言:

有別於掃描的用法。

這次是在App內生成QRCode。

情境可以是給她一個網址參數,或任何字串,然後產生QRcode提供掃描。

像是購物網站,當你買了物品,你想追蹤商品情況時,購物網站可以在訂單查詢內提供QRCode供你掃描查看商品跑去哪了。
可以看看這第三方 https://github.com/zxing/zxing







實作:

等等要操作到的地方



STEP 1 :先匯入專案


兩種匯入方式 兩種選擇其中一種就好,別傻傻的兩個都匯入
第一種
第一種是直接compile
compile 'com.google.zxing:core:3.2.1'
 

 第二種
先把core-3.2.1.jar下載下來。

然後就開始匯入專案了。

匯入專案的地方可以參考這一篇:
http://nikeru8.blogspot.tw/2017/03/androidyoutube-api-youtube-api.html

我在這邊使用另外一種方式,不過大同小異。

下載下來後,把core-3.2.1.jar放到你自己專案的資料夾libs內。(如果沒有此資料夾請自己創)

如果圖片太小可點擊放大
core-3.2.1.jar放入後讓我們回到Android Studio,匯入專案囉

點選左上角選擇「Project」>>  找到「libs」>> 找到「core-3.2.1.jar」 >> 點擊右鍵 >> 選擇「Add As Library...



跳出視窗選擇「app」 >> ok


專案匯入完成囉!


STEP 2:來畫我們的xml

activity_main.xml
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:clickable="true"
        android:gravity="center"
        android:onClick="onbuttonclick"
        android:text="產生QRCode" />

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/button"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="45dp" />
</RelativeLayout>


設置一個Button,等點擊之後生成QRCode


STEP 3:寫Code in JAVA

MainActivity.java
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void onbuttonclick(View view) {
        String QRCodeContent = "http://nikeru8.blogspot.tw/2017/04/third-partyxzingcore-qrcodejar.html";
        int QRCodeWidth = 200;
        int QRCodeHeight = 200;

        //QRCode內容編碼
        Map hints = new EnumMap(EncodeHintType.class);
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");

        MultiFormatWriter writer = new MultiFormatWriter();
        try {
            //ErrorCorrectionLevel容錯率分四級:L(7%) M(15%) Q(25%) H(30%)
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);

            //建立QRCode的資料矩陣
            BitMatrix result = writer.encode(QRCodeContent, BarcodeFormat.QR_CODE, QRCodeWidth, QRCodeHeight, hints);

            //建立矩陣圖
            Bitmap bitmap = Bitmap.createBitmap(QRCodeWidth, QRCodeHeight, Bitmap.Config.ARGB_4444);
            for (int y = 0; y < QRCodeHeight; y++) {
                for (int x = 0; x < QRCodeWidth; x++) {
                    bitmap.setPixel(x, y, result.get(x, y) ? Color.BLACK : Color.WHITE);
                }
            }

            //設定給xml
            ImageView imageView = (ImageView) findViewById(R.id.imageView);
            imageView.setImageBitmap(bitmap);
        } catch (WriterException e) {
            e.printStackTrace();
        }
    }
}

完成囉!
QRCodeContent內就是QRCode產生出來的字串。


eidt(2017/06/12)
我發現如果QRCode你要放到很大很大,直接調整QRCodeWidth和Height會因為產生bitmap而有卡頓狀況。
此時可以用一個方法改善
  bitmap = Bitmap.createScaledBitmap(bitmap,
                    bitmap.getWidth() * 4,
                    bitmap.getHeight() * 4, false);


eidt(2017/11/27)
兩件事
一、控制QRCode旁邊白邊的大小
hints.put(EncodeHintType.MARGIN, 0);
 
後面的0 這個int參數,設得越大白邊就越寬
二、QRCode圖片太大有時候會造成app卡頓
使用AsyncTask http://nikeru8.blogspot.tw/2017/11/androidasynctask_26.html




文獻:
http://gnehcic.azurewebsites.net/android%E5%BB%BA%E7%AB%8Bqr-code/
https://github.com/zxing/zxing


Demo:
https://drive.google.com/open?id=0Byk75IYx-dKXT0dERGdqRVNYSEk


third-party元件(barcodescanner) ─ 簡易掃描QRCode

前言:

如果在Google Play商店搜尋打QRCode,你會發現如沐春雨般的此類App。

這是使用第三方是非常簡單就能實作出來的東西,看來大家都想賺廣告錢啊XD

這次東西有牽涉到
Android元件 ─ 要求權限 Permission 封裝(二)
Android元件(WebView) ─ 內崁網路瀏覽器



QRCODE第三方:https://github.com/dm77/barcodescanner





重要程式碼:

只要記得 implements ZXingScannerView.ResultHandler

和複寫
public void handleResult(final Result rawResult) {
 //do something after scanner
  }

這個方法就好了。
剩下就是簡單的設定問題了。



實作:

今日要實做到的部分。


STEP 1 :先在 build.gradle(Module:app)加入今日的第三方

compile 'me.dm7.barcodescanner:zxing:1.9'


STEP 2 :在AndroidManifest.xml內加入要使用到的權限

   <uses-feature android:name="android.hardware.camera.autofocus" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.INTERNET" />

由上至下的權限分別為:
自動對焦
獲取使用相機
網路使用權

其中只有獲取使用相機是危險權限,所以只有這裡需要額外寫Code和使用者要權限。

STEP 3 ;創建新的Activity和畫xml



在「APP上按右鍵 > NEW > Activit y> Empty Activity
先創建一個新Activity,我命名為ScannerActivity.javaactivity_scanner.xml

先著手開始畫xml
activity_main.xml

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:orientation="vertical"
    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"
    tools:context="com.spinner.a015865.qrcode.MainActivity">

    <TextView
        android:layout_margin="20dp"
        android:onClick="scanCode"
        android:id="@+id/tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="I am Button"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
<WebView
    android:id="@+id/wv"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>
</LinearLayout>
設置一個Button,在Button下面畫一個WebView,當QRCode掃入一個網址後,可以回掉開啟。



activity_scanner.xml
activity_scanner.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    android:id="@+id/main_activity"
    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"
    tools:context="com.spinner.a015865.qrcode.ScannerActivity">
</FrameLayout>


基本上就是空的,唯一需要設置的就是這xml的id。我們之後會用到。

STEP 4 :寫入程式JAVA

MainActivity.java
public class MainActivity extends AppCompatActivity {
    //設置畫面元件
    private TextView mTextView;
    private WebView mWebView;

    //轉畫面的Activity參數
    private Class<?> mClss;

    //
    private static final int ZXING_CAMERA_PERMISSION = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //初始畫面
        initView();
        //初始畫面設置
        initSet();


    }


    //起始畫面
    private void initView() {
        mTextView = (TextView) findViewById(R.id.tv);
        mWebView = (WebView) findViewById(R.id.wv);
    }

    //起始畫面設置
    private void initSet() {

        /**
         * 以下都是WebView的設定
         * */
        WebSettings websettings = mWebView.getSettings();
        websettings.setSupportZoom(true); //啟用內置的縮放功能
        websettings.setBuiltInZoomControls(true);//啟用內置的縮放功能
        websettings.setDisplayZoomControls(false);//讓縮放功能的Button消失
        websettings.setJavaScriptEnabled(true);//使用JavaScript
        websettings.setAppCacheEnabled(true);//設置啟動緩存
        websettings.setSaveFormData(true);//設置儲存
        websettings.setAllowFileAccess(true);//啟用webview訪問文件數據
        websettings.setDomStorageEnabled(true);//啟用儲存數據
        mWebView.setWebViewClient(new WebViewClient());
    }

    //Button的設置
    public void scanCode(View view) {
//        startActivityForResult(new Intent(this, ScannerActivity.class), 1);
        launchActivity(ScannerActivity.class);
    }

    //轉畫面的封包,兼具權限和Intent跳轉化面
    public void launchActivity(Class<?> clss) {
        //假如還「未獲取」權限
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
                != PackageManager.PERMISSION_GRANTED) {
            mClss = clss;
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.CAMERA}, ZXING_CAMERA_PERMISSION);
        } else {
            Intent intent = new Intent(this, clss);
//            startActivity(intent);
            startActivityForResult(intent, ZXING_CAMERA_PERMISSION);
        }
    }

    //當ScannerActivity結束後的回調資訊
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == RESULT_OK) {
            Log.d("checkpoint", "CheckPoint");
            mTextView.setText(data.getStringExtra("text"));

            mWebView.loadUrl(data.getStringExtra("text"));
        }
    }
}

MainActivity內我使用到了WebViewPermission的封包方法。詳情點連結。

ScannerActivity.java
public class ScannerActivity extends Activity implements ZXingScannerView.ResultHandler {
    private ZXingScannerView mScannerView;

    @Override
    public void onCreate(Bundle state) {
        super.onCreate(state);
        setContentView(R.layout.activity_scanner);
        //設置畫面
        ViewGroup contentFrame = (ViewGroup) findViewById(R.id.main_activity);
        //設定Scanner
        mScannerView = new ZXingScannerView(this);
        //把Scanner加入
        contentFrame.addView(mScannerView);
//        setContentView(mScannerView);
    }

    @Override
    public void onResume() {
        super.onResume();
        //設置Scanner的回調
        mScannerView.setResultHandler(this);
        //開啟相機
        mScannerView.startCamera();
    }

    @Override
    public void onPause() {
        super.onPause();
        //停止相機
        mScannerView.stopCamera();
    }

    //設定回調,當你掃完QR你將要做的事情
    @Override
    public void handleResult(final Result rawResult) {
        Toast.makeText(this, "Contents = " + rawResult.getText() +
                ", Format = " + rawResult.getBarcodeFormat().toString(), Toast.LENGTH_SHORT).show();

        /**
         * 這邊等兩秒才回調資料
         * 比較舊的設備有時候會產生無法預期的錯誤
         * 這邊作者使用延遲兩秒去debug
         * */
        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                //把掃描到的資料回調到MainActivity
                Intent data = new Intent();
                data.putExtra("text", rawResult.getText());
                setResult(RESULT_OK, data);
                finish();
                mScannerView.resumeCameraPreview(ScannerActivity.this);
            }
        }, 2000);
    }
}


完成囉!





Demo:
https://drive.google.com/open?id=0Byk75IYx-dKXT0dERGdqRVNYSEk




2017年4月19日 星期三

Android元件 ─ 要求權限 Permission 封裝(二)

前言:

前一篇在這裡:
http://nikeru8.blogspot.tw/2017/04/android-permission.html

這篇只是把Permission和Intent做個封裝。

大致上長這樣。

讓我們開始吧。



重點程式碼:

//設定Activity頁面參數
private Class<?> mClss;

 public void launchActivity(Class<?> clss) {
        //如果沒有權限
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
                != PackageManager.PERMISSION_GRANTED) {
            mClss = clss;
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.CAMERA}, 
                    CUSTOM_NUMBER);
        } else {
            Intent intent = new Intent(this, clss);
            startActivity(intent);
        }
    }

一言蔽之,就是如果你要使用相機功能,沒有權限的話幫你導到權限畫面,如果之前已經取過權限,則直接進入。




實作:

先來看看我們今天會動到的地方。


先創一個Activity,我這邊命名為 activity_part_two.xmlPartTwoActivity

先給予這App權限吧。

STEP 1:給予相機權限


AndroidManifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.spinner.a015865.permission">

   <uses-permission android:name="android.permission.CAMERA"/>
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".PartTwoActivity"/>
    </application>

</manifest>

STEP 2:創建第二個Activity並畫XML

activity_main.xml

activity_main.xml
<?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"
    tools:context="com.spinner.a015865.permission.MainActivity">

   <Button
       android:text="要權限+切到畫面B"
       android:onClick="Button_to_next"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content" />

</android.support.constraint.ConstraintLayout>


activity_part_two.xml

activity_part_two.xml
<?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"
    tools:context="com.spinner.a015865.permission.PartTwoActivity">

    <TextView
        android:textSize="50dp"
        android:text="BBBBBBBBB"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</android.support.constraint.ConstraintLayout>


STEP 3:實作JAVA部分

第一個Activity才是重點。

第二個新創的Activity是空的,示意一下而已,在這邊把所有的程式碼都貼上以示完整。

MainActivity.java
public class MainActivity extends AppCompatActivity {
    private Class<?> mClss;
    private static final int CUSTOM_NUMBER = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void Button_to_next(View view) {
        launchActivity(PartTwoActivity.class);
    }

    public void launchActivity(Class<?> clss) {
        //如果沒有權限
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
                != PackageManager.PERMISSION_GRANTED) {
            mClss = clss;
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.CAMERA},
                    CUSTOM_NUMBER);
        } else {
            Intent intent = new Intent(this, clss);
            startActivity(intent);
        }
    }
}

PartTwoActivity
public class PartTwoActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_part_two);
    }
}


完成囉!




Demo:
https://drive.google.com/open?id=0Byk75IYx-dKXeV9nOWFWOHFIc1E







Android元件 ─ 要求權限 Permission (一)

前言:

權限其實沒有想像中的困難 。

在Android版本6.0以上,為了安全設計,就全面要求app要和使用者要求權限。

市面上還出現了像是EasyPermissions這類專門幫你拿取權限的第三方套件。

但我認為完全沒有必要使用這類的第三方,因為拿取權限並沒有想像中的那麼困難,也真的像那個第三方套件的名稱一樣,真的很Easy。

今日實作影片


這是今日要做的小範本。




重點程式碼:



if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
  //還沒獲取權限要做什麼呢

  //和使用者要求權限
  ActivityCompat.requestPermissions(MainActivity.this,
                   new String[]{Manifest.permission.CAMERA},
                   1);
}else{
  //以獲取權限要做的事情

  Toast.makeText(this, "已經拿到權限囉!", Toast.LENGTH_SHORT).show();
}
/**
*requestPermissions 是用來要求使用者給予權限的方法(method)
*第一個參數 此頁面
*第二個參數 要獲取的權限名稱
*第三個參數 自定義的請求代碼
*/




實作:

首先你要先想清楚這個App所要那些權限(permission)。

有分為一般權限危險權限,也只有危險權限才會跳出視窗和使用者要求使用它。


這邊就先拿相機Camera權限來做示範。

今日要動到的地方main_activity.xml、MainActivity.java、Manifest
main_activity.xml、MainActivity.java、Manifest

STEP 1:在Manifest內設定權限

AndroidManifest
  
    //Manifest
  <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.spinner.a015865.permission">

    <uses-permission android:name="android.permission.CAMERA"/>
    <application
       ...
    </application>

</manifest>

STEP 2:實作activity_main.xml

簡單的在一開始的畫面給一個Button吧。
main_activity.xml
main_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    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"
    tools:context="com.spinner.a015865.qrmaker.MainActivity">

    <TextView
        android:layout_centerInParent="true"
        android:textSize="30dp"
        android:textColor="@android:color/black"
        android:onClick="button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="button" />

</RelativeLayout>




STEP 3:實作MainActivity.java

MainActivity.java
public class MainActivity extends AppCompatActivity {


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void button(View view) {

        //檢查是否取得權限
        int permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA);

        //沒有權限時
        if (permissionCheck != PackageManager.PERMISSION_GRANTED) {

            ActivityCompat.requestPermissions(MainActivity.this,
                    new String[]{Manifest.permission.CAMERA},
                    1);
        } else {
            Toast.makeText(this, "已經拿到權限囉!", Toast.LENGTH_SHORT).show();
        }
    }
    
}

解析:

int permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA);

比較需要注意的是,這是一個int值。用來確定是否獲取權限。


如果使用者「同意權限」、「拒絕權限」

●已批准 PERMISSION_GRANTED 
//英文大補帖GRANTED已批准的

●已拒絕 PERMISSION_DENIED
//英文大補帖DENIED已拒絕的


int permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA);

if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
   //還沒獲取權限要做什麼呢
}else{
   //以獲取權限要做的事情
}

要求權限

如果使用者還沒給予權限,就要求使用者給予,跳視窗提醒它我要權限囉。
//自定義的請求代碼
//private static final int CUSTOM_NUMBER = 1;
if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
   //還沒獲取權限要做什麼呢
     ActivityCompat.requestPermissions(MainActivity.this,
                    new String[]{Manifest.permission.CAMERA},
                    CUSTOM_NUMBER);
}else{
   //以獲取權限要做的事情
   Toast.makeText(this, "已經拿到權限囉!", Toast.LENGTH_SHORT).show();
}


/**
*requestPermissions 是用來要求使用者給予權限的方法(method)
*第一個參數 此頁面
*第二個參數 要獲取的權限名稱
*第三個參數 自定義的請求代碼(後面會用到)
*/
很簡單吧。

Demo:
https://drive.google.com/open?id=0Byk75IYx-dKXelNXaE05aTBMOUk



客製化用法 一:允許或拒絕之後的動作(onRequestPermissionsResult )

上面已經可以獲取你想要的權限無礙了。

再來講一些比較客製化獲取權限的方式。





















按下允許或是拒絕都可以幹些什麼事情。
我這邊是讓他們跳出Toast
 


在MainActivity.java內,多複寫一個繼承的方法。
/**
     * public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
     * 複寫請求授權後執行的方法
     * 第一個參數是請求代碼
     * 第二個參數是請求授權的名稱
     * 第三個參數是請求授權的結果,PERMISSION_GRANTED或PERMISSION_DENTED
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        //這個"CUSTOM_NUMBER"就是上述的自訂意義的請求代碼
        // private static final int CUSTOM_NUMBER = 1;
        if (requestCode == CUSTOM_NUMBER) {
            //假如允許了
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                //do something
                Toast.makeText(this, "已經拿到CAMERA權限囉!", Toast.LENGTH_SHORT).show();
            } 
            //假如拒絕了
            else {
                //do something
                Toast.makeText(this, "CAMERA權限FAIL", Toast.LENGTH_SHORT).show();
            }
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

客製化用法 二 :半客製化要求使用者給予權限(shouldShowRequestPermissionRationale)

為什麼前面加一個「半」呢?

因為不是真正的你想的那樣。
這是當你第一次和使用者伸手要權限被拒絕時,第二次要求的時刻,才會跳出的視窗

大致上的用法就是請你再詳細解釋一下為什麼需要用到這個權限。



MainActitivy.javaButton裡面的requestPermissions方法
//
if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
   //在這裡面做文章
 }

Button方法
//
    public void button (View view) {
        //檢查是否取得權限
        int permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA);

        //沒有權限時
        if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
            //如果使用者第二次點擊功能呼叫權限視窗,就會跳出shouldShowRequestPermissionRationale
            if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
                    Manifest.permission.CAMERA)) {
                //創建Dialog解釋視窗
                new AlertDialog.Builder(MainActivity.this)
                        .setMessage("單純使用在拍照功能,如果您不給我相機的權限,您將無法使用此功能")
                        .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                ActivityCompat.requestPermissions(MainActivity.this,
                                        new String[]{Manifest.permission.CAMERA},
                                        CUSTOM_NUMBER);
                            }
                        })
                        .setNegativeButton("No", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                finish();
                            }
                        })
                        .show();
            } else {
                ActivityCompat.requestPermissions(MainActivity.this,
                        new String[]{Manifest.permission.CAMERA},
                        CUSTOM_NUMBER);
            }
        } else {
            Toast.makeText(this, "已經拿到權限囉!", Toast.LENGTH_SHORT).show();
        }
    }



Demo:
https://drive.google.com/open?id=0Byk75IYx-dKXR2dtMmdFNVJndXM

總結:

下一篇講一下我最常用的方法,一個按鈕解決切畫面要求權限雙重效果。
其實就是封裝一下Permission和Intent而已。
在第二篇做說明。

有問題歡迎提出唷!

文獻:
https://developer.android.com/reference/android/Manifest.permission.html
https://developer.android.com/guide/topics/permissions/index.html
https://developer.android.com/guide/topics/manifest/uses-permission-element.html

2017年4月17日 星期一

Android元件 ─ 最簡單的Spinner

前言:

這種Spinner的方式算是我最愛的一種吧。

最為直觀、簡單。







實作:

實作影片

這次要控制的地方有三個

strings、main_activity.xml、MainActivity.java

strings、main_activity.xml、MainActivity.java





















先從strings.xml下手,在strings.xml內設置你要的陣列單位。
先找到res/values/strings.xml
<resources>
    <string name="app_name">SpinnerHello</string>

 <string-array name="Colors">
        <item>gray</item>
        <item>blue</item>
        <item>red</item>
        <item>yellow</item>
        <item>oragne</item>
    </string-array>
</resources>



main_activity.xml





















main_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
    tools:context="com.spinner.a015865.spinnerhello.MainActivity">

    <Spinner
        android:id="@+id/spinner_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="30dp"
        android:entries="@array/Colors" />

    <TextView
        android:id="@+id/textview_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="Hello World!"
        android:textSize="50dp" />

    <Button
        android:id="@+id/button_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="PressMe" />

</LinearLayout>



MainActivity.java
public class MainActivity extends AppCompatActivity {

    private TextView mTextView;
    private Spinner mSpinner;
    private Button mButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initView();
        initSet();
        initListener();
    }

    private void initView() {
        mTextView = (TextView) findViewById(R.id.textview_view);
        mSpinner = (Spinner) findViewById(R.id.spinner_view);
        mButton = (Button) findViewById(R.id.button_view);
    }

    private void initSet() {
    }

    private void initListener() {
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String message = String.valueOf(mSpinner.getSelectedItem());
                mTextView.setText(message);
            }
        });
    }
}



超簡單的Spinner就完成囉!



Demo:

https://drive.google.com/open?id=0Byk75IYx-dKXbWZPOTU1WHdKSm8





2017年4月10日 星期一

改變strings.xml ─ String.format()的使用

實作:

strings.xml

 
 //
 <string name="Test_Number">TestNumber %1$d 測試數字</string>
 <string name="Test_Word">TestNumber %1$s 測試國字</string>



此時要如何在java內操作%1$d%1$s呢?

先來搞懂上述各代表什麼。

前面的%n代表是第幾個參數

%d(表示整數)
%f(表示浮點數)
%s(表示字符串)



 先畫xml,在xml內畫兩個TextView
activity_main.xml

activity_main.xml

<?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"
    tools:context="com.chat.a015865.customdialog.MainActivity">
     
    <TextView
        android:id="@+id/textview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:onClick="onClickMe"
        android:text="Hello World!" />

    <TextView
        android:id="@+id/textViewtwo"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/textview"
        android:layout_centerHorizontal="true"
        android:text="Hello Text Two" />

</RelativeLayout>


MainActivity.java

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView textView = (TextView) findViewById(R.id.textview);
        TextView textviewtwo = (TextView) findViewById(R.id.textViewtwo);

        String message = getString(R.string.Test_Number);
        String messagetwo = getString(R.string.Test_Word);

        textView.setText(String.format(message, 123789));
        textviewtwo.setText(String.format(messagetwo, "三十國字哈囉"));

    }
}


/**
*String.format(strings,value);
*strings 是strings.xml內的字串參數(ex:TestNumber %1$d 測試數字)
*value 是你帶給%1$d的值
*/

實作完成畫面
實作完成畫面





簡易好懂:
http://blog.csdn.net/xiaoyaovsxin/article/details/8450056

詳細版本:
http://blog.csdn.net/lonely_fireworks/article/details/7962171

Android元件(Dialog) ─ 自定義Dialog(PopupView的取代方法)

前言:




上次說到PopupWindow在Android 7 以上產生的bug,這邊提供另外一種解決方式。
同場加映:http://nikeru8.blogspot.tw/2017/03/androidpopupwindowpopupview-popupwindow.html

可以使用自定義的Dialog。

這方法是使用Activity當作Dialog來使用




實作:

先來說明此次會動到的地方。

創建一個專案後。

直接開啟一個新的Activity。


這個Activity我們要拿來當作Dialog使用。
Java ActivityName取名為DialogActivity
LayoutName取名為activity_dialog

先設定背景圖片
參考:http://nikeru8.blogspot.tw/2017/03/textview.html

在drawable資料夾內創建一個背景圖片,取名為rectangle_drawable。


drawable/rectangle_drawable
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >

    <corners
        android:topLeftRadius="5sp"
        android:topRightRadius="5sp"
        android:bottomLeftRadius="5sp"
        android:bottomRightRadius="5sp" />
    <solid android:color="@android:color/white" />
    <stroke
        android:width="2dip"
        android:color="#0290D2" />

</shape>


接下來設計一下您想要的Dialog Layout
activity_dialog.xml
activity_dialog.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:padding="10dp"
    android:orientation="vertical"
    android:background="@drawable/rectangle_drawable">
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:layout_margin="18dp"
        android:padding="5dp"
        android:text="Hello"
        android:textColor="@color/dark_text" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:layout_margin="18dp"
        android:padding="5dp"
        android:text="@android:string/ok"
        android:onClick="clickfinish" />
</LinearLayout>


DialogActivity.java 
public class DialogActivity extends Activity {//這邊請extands Activity

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // 這一行是來取消TitleBar用的
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_dialog);
    }

    public void clickfinish(View view) {
        finish();
    }
}


讓畫面帶到AndroidManifest
 <activity
            android:name=".DialogActivity"
            android:theme="@android:style/Theme.Dialog"/>


讓這個Activity繼承Dialog的主題!
差不多完成囉!


接下來直接在MainActivity內連接Button接到DialogActivity就行了。
activity_main

activity_main.xml
<?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"
    tools:context="com.chat.a015865.customdialog.MainActivity">
    //這是一個BUTTON
    <TextView
        android:onClick="onClickMe"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

MainActivity.java
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void onClickMe (View view) {
        Intent intent = new Intent(this, DialogActivity.class);
        startActivity(intent);
    }
}


現在跑跑看吧!
一個自定義的Dialog就完成囉!



如果要在這個自定義的Dialog內帶資料回MainActivity,直接使用Bundle 或是 startActivityForResult都行。







DEMO:
https://drive.google.com/open?id=0Byk75IYx-dKXcDdBYjJrZ2ZUTzg







協程(coroutine) - 協程為什麼要學它?

 Coroutine 協程 再強調一次 協程就是由kotlin官方所提供的線程api //Thread Thread { }.start() //Executor val execu...