2016/12/29

How to correctly get screenshot from MediaProjection without black area

Step 1 Request a MediaProjection object
MediaProjectionManager projectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
startActivityForResult(projectionManager.createScreenCaptureIntent(), /*YOUR_REQUEST_CODE*/);

Step 2 Once user submit the permission request dialog, you can get a MediaProjection object in
MediaProjectionManager projectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
MediaProjection mProjection = projectionManager.getMediaProjection(resultCode, data);

Step 3 Create an ImageReader and a screen-size-fit VirtualDisplay
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
final DisplayMetrics metrics = new DisplayMetrics();
display.getMetrics(metrics);
Point size = new Point();
display.getRealSize(size);
final int mWidth = size.x;
final int mHeight = size.y;
int mDensity = metrics.densityDpi;

final ImageReader mImageReader = ImageReader.newInstance(mWidth, mHeight, PixelFormat.RGBA_8888, 2);

final Handler handler = new Handler();

int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY | DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
mProjection.createVirtualDisplay("screen-mirror", mWidth, mHeight, mDensity, flags, mImageReader.getSurface(), null, handler);

Step 4 Get screenshot in OnImageAvailableListener
mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
            @Override
            public void onImageAvailable(ImageReader reader) {
                reader.setOnImageAvailableListener(null, handler);

                Image image = reader.acquireLatestImage();

                final Image.Plane[] planes = image.getPlanes();
                final ByteBuffer buffer = planes[0].getBuffer();
    
                int pixelStride = planes[0].getPixelStride();
                int rowStride = planes[0].getRowStride();
                int rowPadding = rowStride - pixelStride * metrics.widthPixels;
                // create bitmap
                Bitmap bmp = Bitmap.createBitmap(metrics.widthPixels + (int) ((float) rowPadding / (float) pixelStride), metrics.heightPixels, Bitmap.Config.ARGB_8888);
                bmp.copyPixelsFromBuffer(buffer);

                image.close();
                reader.close();

                Bitmap realSizeBitmap = Bitmap.createBitmap(bmp, 0, 0, metrics.widthPixels, bmp.getHeight());
                bmp.recycle();
    
                /* do something with [realSizeBitmap] */
            }
        }, handler);

For full example code you can found at https://github.com/firemaples/EverTranslator/blob/master/deprecated/src/main/java/tw/firemaples/onscreenocr/screenshot/ScreenshotHandler.java
Kotlin version: https://github.com/firemaples/EverTranslator/blob/master/main/src/main/java/tw/firemaples/onscreenocr/screenshot/ScreenExtractor.kt

Reference:

http://binwaheed.blogspot.tw/2015/03/how-to-correctly-take-screenshot-using.html

2016/4/12

修復 MSSQL 資料庫[有疑問]狀態 (可能會遺失部分未存入硬碟的資料)

在SQL Server中執行下列指令修復資料庫
DECLARE @Dbname NVARCHAR(50) = 'DBNAME' --Replace to target db name

DECLARE @Sql NVARCHAR(MAX) = ''
SET @Sql = @Sql+'EXEC sp_resetstatus ['+@Dbname+'];'
SET @Sql = @Sql+'ALTER DATABASE ['+@Dbname+'] SET EMERGENCY;'
SET @Sql = @Sql+'DBCC CheckDB(['+@Dbname+']);'
SET @Sql = @Sql+'ALTER DATABASE ['+@Dbname+'] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;'
SET @Sql = @Sql+'DBCC CheckDB(['+@Dbname+'], REPAIR_ALLOW_DATA_LOSS);'
SET @Sql = @Sql+'ALTER DATABASE ['+@Dbname+'] SET MULTI_USER;'

PRINT @Sql
EXEC [sp_executesql]
     @Sql;

參考網站: https://support.managed.com/kb/a398/how-to-repair-a-suspect-database-in-mssql.aspx

2015/11/16

Android drawable-hdpi-v4\ic_launcher.png duplicate error


:metaioSDK_Test-GuideMan:processDebugResources
xxxx\build\intermediates\res\merged\debug\drawable-hdpi-v4\ic_launcher.png: error: Duplicate file.
xxxx\build\intermediates\res\merged\debug\drawable-hdpi\ic_launcher.png: Original is here. The version qualifier may be implied.
Error:Execution failed for task ':metaioSDK_Test-GuideMan:processDebugResources'.
> com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process 'command 'D:\adt-bundle-windows\sdk\build-tools\23.0.1\aapt.exe'' finished with non-zero exit value 1

出現以上紅色的問題,是因為所使用的 Library 中有包含 drawable-hdpi-v4\ic_launcher.png 的檔案造成的問題,最簡單的解決方法就是將自己 Module 中的 ic_launcher.png 檔改名(如: appicon.png),並且 AndroidManifest.xml 中的 icon 也引用改名後的檔名(如: appicon.png)就可以解決了。


使用 Android Studio 的變更方法可以參考以下:

1.左上角檢視類型選擇 [Android] => 點選專案裡的 [ic_launcher.png] 檔案 => [Shift + F6] 彈出重新命名視窗,輸入 [appicon.png] 之後按下 [Enter] 或點選 [Refactor]按鈕






2. 若有彈出確認視窗請點選 [Yes] 及 [Continue]

3.在下方的 [Refactoring Preview] 的視窗中對 [References in generated code to file] 點選 [右鍵] => 選擇 [Exclude] => 之後點選左下角的 [Do Refactor] 就完成了

method ID not in [0, 0xffff]: 65536



UNEXPECTED TOP-LEVEL EXCEPTION:
com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536
at com.android.dx.merge.DexMerger$6.updateIndex(DexMerger.java:502)
at com.android.dx.merge.DexMerger$IdMerger.mergeSorted(DexMerger.java:277)
at com.android.dx.merge.DexMerger.mergeMethodIds(DexMerger.java:491)
at com.android.dx.merge.DexMerger.mergeDexes(DexMerger.java:168)
at com.android.dx.merge.DexMerger.merge(DexMerger.java:189)
at com.android.dx.command.dexer.Main.mergeLibraryDexBuffers(Main.java:502)
at com.android.dx.command.dexer.Main.runMonoDex(Main.java:334)
at com.android.dx.command.dexer.Main.run(Main.java:277)
at com.android.dx.command.dexer.Main.main(Main.java:245)
at com.android.dx.command.Main.main(Main.java:106)


出現這樣的錯誤訊息表示所使用的 method 數量超過 65536 個的限制,只要為 build.gradle 文件加上下方有加底線的程式碼即可

※注意: 改完之後要 [Clear Project] 一次,如果要發布在已經裝有前一個版本的設備時,需要手動先移除程式後再發布

apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.1"

    defaultConfig {
        applicationId "tw.blogspot.firemaples"
        minSdkVersion 15
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
        // Enabling multidex support.
        multiDexEnabled true

    }
    dexOptions {
        incremental false
        preDexLibraries = false
        jumboMode = false
    }
    buildTypes {
        release {
            minifyEnabled false
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    compile 'com.android.support:appcompat-v7:23.1.1'
}

Android 23.0.0 res build error



D:\tfs1\BokerAndroidForStudio\Boker_Navigation\NavigationMapLib\build\intermediates\exploded-aar\com.android.support\appcompat-v7\23.0.0\res\values-v23\values-v23.xml
Error:(2) Error retrieving parent for item: No resource found that matches the given name 'android:TextAppearance.Material.Widget.Button.Inverse'.
Error:(2) Error retrieving parent for item: No resource found that matches the given name 'android:Widget.Material.Button.Colored'.
Error:Execution failed for task ':NavigationMapLib:processReleaseResources'.
> com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process 'command 'D:\adt-bundle-windows\sdk\build-tools\20.0.0\aapt.exe'' finished with non-zero exit value 1


android {
    compileSdkVersion 23 //將 compileSdkVersion 替換成23版以上
    buildToolsVersion "23.0.1" //及 buildToolsVersion 替換成23.0.1版以上即可

    defaultConfig {
        minSdkVersion 15
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
}

2015/9/23

SSRS 安裝 ActiveX 時出現 "列印無法使用。..." 提示視窗


在幫客戶端電腦安裝SSRS ActiveX時遇上"列印無法使用。..."的問題,發生問題的環境如下:
客戶端環境: Windows 7
伺服器環境: Windows Server 2012 + SQL Server 2014
這裡附上英文的錯誤訊息圖(解決了才發現忘了截圖):


問題解決方式如下:
  1. 客戶端電腦安裝 Microsoft Visual C++ 2010 Redistributable Package (x86)
  2. 關閉頁籤再開啟網頁



如果失敗的話,可以建立一個bat檔放置以下內容,再以[系統管理員身分執行],來清除以安裝的ActiveX,再重新執行上面所述步驟
regsvr32 /u "C:\Windows\Downloaded Program Files\RSClientPrint.dll"

del "C:\windows\system32\RSClientPrint.dll" 
del "C:\windows\system32\RSClientPrint*.rll" 
del "C:\windows\system32\RSClientPrint*.inf" 
del "C:\Windows\Downloaded Program Files\RSClientPrint.dll" 
del "C:\Windows\Downloaded Program Files\RSClientPrint*.rll" 
del "C:\Windows\Downloaded Program Files\RSClientPrint*.inf" 


參考資料:
 MSDN:Unable to install Client Print Control for SSRS 2014 onto a 32-bit Windows 7 PC

2015/5/5

計算兩點之間連線的方位角[網路修改版]

網路上找到的程式碼算出來的都是與縱軸的最小夾角,加了一點程式碼讓結果變為與北方的方位角

private static double gps2d(double lat_a, double lng_a, double lat_b, double lng_b) {
  double d = 0;
        lat_a = lat_a * Math.PI / 180;
        lng_a = lng_a * Math.PI / 180;
        lat_b = lat_b * Math.PI / 180;
        lng_b = lng_b * Math.PI / 180;

        d = Math.sin(lat_a) * Math.sin(lat_b) + Math.cos(lat_a) * Math.cos(lat_b) * Math.cos(lng_b - lng_a);
        d = Math.sqrt(1 - d * d);
        d = Math.cos(lat_b) * Math.sin(lng_b - lng_a) / d;
        d = Math.asin(d) * 180 / Math.PI;

        if (lat_b >= lat_a) {
            if (d < 0) {
                d = 360 + d;
            }
        } else {
            d = 180 - d;
        }

        return d;
 }
http://ideone.com/woZsDA