Day 6 - 唯一与职缺有关的工作内容

新鲜人进入职场总是会充满干劲,然後希望能够一步一步克服重重难关突破自己的极限,但是怎麽做的事情越来越偏移当初面试提到的工作内容,而且还是需要写之前比较少接触的程序语言....

此系列唯一与Android相关的技术文章

昨天的文章提到的推荐套件和开发环境怎麽跟Android没有太多的关联,因为在执行多个专案与Android关系的就只有一个。因此这一篇会浓缩分享跟当初面试提到与工作内容有关的专案,後续的系列文章基本上不会看到跟Android有关的事情和技术内容。

看到这会想说哇赛那这样是不是系列文章差不多要结束了,不过人生有趣的地方就是在一些时间点会有惊奇和意料之外的事情发生,因此也没有因为这样的情况就马上开104去寻找下一份工作xD。

/images/emoticon/emoticon76.gif

专案的缘由

这个专案合作的对象是印刷背景的厂商,而该厂商的需求就是希望透过影像辨识的方式去检验印刷出来的防伪标签品质,而辨识的型态包含照片以及即时辨识。接着在分工的部分主要就是从无到有建立一个App,并且去开发KPI有列出来的功能,在开发前需要分几个面向确认多个功能实现的方法以及可以参考的来源。

开发前的前置作业

在开发Android的APP所使用的IDE可以使用Android Studio进行开发,另外在电脑配备的部分如果是使用模拟器检视开发後的功能与画面,建议记忆体起码也要8G比较好(以前笔电只有8G的时候还被研习的同事嫌怎麽跑那麽慢xD)。当第一次安装好之後如果要启用模拟器可以点选画面右上角的AVD Manage,接着选择要测试的版本以及虚拟机型号安装後再点击三角型开始的符号确定有没有正常启动。
Imgur

画面要怎麽呈现?

当时在画面的呈现询问了同事有没有参考的版本,於是它就开启APP inventor跟我说它之前设计的初版,当时我看到後也得知之前的计画跟APP有关的都是用这个工具开发,然後内心默默接受原来部门没有人知道怎麽使用Android Studio开发,而且如果我开发遇到的问题也没有人可以问...

但怎麽可以这样就放弃了呢?

於是确认了基本功能会对应到的画面後,为了能够响应不同萤幕大小的装置首选的layout使用了ConstraintLayout,讲到这里想到大学时如果有推出这个拉画面的痛苦感可以减少一点了QQ。然而在拉画面的过程中除了使用UI的画面拉取物件排版之外,自己的习惯是再使用程序码确认每个物件参数的设定。

Imgur
设计画面时可以用split的方式确认物件的位置相关参数

接着则是物件设计後需要有文字的显示,而过去常常会直接在android:text後面直接加文字,但如果画面的文字未来假如需要更换这些字串,除了很耗时间去找到不同类别内的字串外,在会因为打错字而出现不必要的bug。所以说将字串的定义抽离统一放在strings.xml内,後续维护可以集中修改xml档案就可以了。

Imgur

开发流程小点滴分享

接着分享过去写的一些功能(久违的开启之前写的程序码回忆一下),由於照片读取後辨识的那些行为比较机密因此未来如果还有一头栽进Android的世界也许可以再来分享一下。

备注:下述的范例程序码为部分撷取,若有变数上的缺漏或者是结构上问题系列文章结束有时间会再更新。

private void ScalePic(Bitmap bitmap, int phone) {
    // 缩放比例预设为1
    float mScale = 1;
    // 如果图片宽度大於手机宽度则进行缩放,否则直接将图片放入ImageView内
    if (bitmap.getWidth() > phone) {

        //判断缩放比例
        mScale = (float) phone / (float) bitmap.getWidth();

        Matrix mMat = new Matrix();
        mMat.setScale(mScale, mScale);

        Bitmap mScaleBitmap = Bitmap.createBitmap(bitmap, 0,
                0,
                bitmap.getWidth(),
                bitmap.getHeight(),
                mMat,
                false);
        imageview.setImageBitmap(mScaleBitmap);
    }
    // 照片显示於手机上
    else imageview.setImageBitmap(bitmap);
}

那时候测试拍照後的照片显示到手机时,测试机的萤幕实在太小因此後续才会有这个的判断行为

// 取得选取相片的档案路径
public String getPath(Uri uri) {
    String[] projection = {MediaStore.Images.Media.DATA};
    Cursor cursor = managedQuery(uri, projection, null, null, null);
    int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
    cursor.moveToFirst();
    return cursor.getString(column_index);
}

取得相簿内照片路径的行为

// 画面延迟载入至首页
final Intent intent = new Intent(this, MainPageActivity.class);
Timer timer = new Timer();
TimerTask task = new TimerTask() {
    @Override
    public void run() {
        startActivity(intent);
    }
};
timer.schedule(task, 2000);

这个是当时想要做画面载入等待的效果xD

private void openImageChooserActivity() {
        Intent i = new Intent(Intent.ACTION_GET_CONTENT);
        i.addCategory(Intent.CATEGORY_OPENABLE);
        i.setType("image/*");
        startActivityForResult(Intent.createChooser(i, "Image Chooser"), FILE_CHOOSER_RESULT_CODE);                                
}
//webview呼叫使用图片上传参数
private ValueCallback<Uri> uploadMessage;
private ValueCallback<Uri[]> uploadMessageAboveL;
private final static int FILE_CHOOSER_RESULT_CODE = 10000;

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {

    //判断webview选取图片後回传的行为
    if (requestCode == FILE_CHOOSER_RESULT_CODE) {
        if (null == uploadMessage && null == uploadMessageAboveL) return;
        Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();
        if (uploadMessageAboveL != null) {
            onActivityResultAboveL(requestCode, resultCode, data);
        } else if (uploadMessage != null) {
            uploadMessage.onReceiveValue(result);
            uploadMessage = null;
        }
    }

    if (requestCode == 1 && resultCode == RESULT_OK) {
        selectedImageUri = data.getData();
        imagepath = getPath(selectedImageUri);
        File f = new File(ImageSelectUtils.getRealPath(selectedImageUri, getApplicationContext()));
        Bitmap bitmap = BitmapFactory.decodeFile(imagepath);
        int bitmap_width = bitmap.getWidth();
        int bitmap_height = bitmap.getHeight();

        DisplayMetrics dm = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(dm);
        int screenWidth = dm.widthPixels;
        if (bitmap_width <= screenWidth) {
            imageview.setImageBitmap(bitmap);
        } else {
            Bitmap bmp = Bitmap.createScaledBitmap(bitmap, screenWidth, bitmap_height * screenWidth / bitmap_width, true);
            imageview.setImageBitmap(bmp);
        }
        messageText.setText("Uploading file path:" + imagepath);
    }
    super.onActivityResult(requestCode, resultCode, data);
}

另外像是Activity间传递和接收结果的使用startActivityForResult与onActivityResult的行为

相关参考资讯

专案执行期间到结束的心得

当时功能写到卡住一个地方卡太久真的很痛苦

执行这个专案的过程完全没有可以参考的程序码(App inventor的功能大多都是画面单纯切换的功能),虽然同事有把OpenCV的相关书籍给我参考但那时候每天都满满的疑惑(影像处理的知识非常薄弱),光是确认照片拍完後与同事写的影像判断行为串接一起花费蛮大的功夫。除此之外由於同事的专长语言是python,因此开发过程中如果有Java语法上的问题完全没办法开话题,只能透过错误讯息的关键字以及问题可能的方向一步一步进行测试,幸好最後有把厂商需要的功能完成并且顺利结案。

虽然工作到现在只有这个专案跟当时的职缺名称有相关,但写着写着自己的内心渐渐的没有那麽坚持着一定要做跟之前实习有关的相关内容,反而更想接触新的程序语言或者是颇具挑战的专案。不过也因为工作的环境又思考着没有前辈带领,以及没有像小组方式开发的限制条件下,自己真的可以依照自己的想法持续下去吗?


题外话

另外如果有想要练习Kotlin语言开发的大家可以去参加国内办的一些课程(参赛完还会有奖品 赞 !)
https://events.withgoogle.com/android-study-jam-twhk-2021/#content


<<:  Day 10 - Hold Shift to Check Multiple Checkboxes

>>:  [想试试看JavaScript ] 函式

【DAY 26】软件拖垮效率?你有想过你需要打开多少应用程序才能完成工作吗?

哈罗大家好~~ 昨天的 Microsoft 365介绍方案告一段落,不知道大家对於Microsoft...

[Day29] RSI指标

今天做的是RSI指标,他是用一个公式去测量过去一段周期内的涨跌强弱,然後用0~100的数据来表示,越...

第14天 - PHP 简易登入(1)_HTML的部分

首先把之见前建立的 表staff 加入【密码栏位】。 (为了方便,密码都设个位数XD) (以下凭我印...

Day 22 : Docker化Jmeter 与连结Jenkins自动化测试

在一个专案Build完成後,通常会跑一些测试来检测这个专案到底能够承受多少的流量与有没有一些会影响使...

资讯安全

-资讯安全 安全是指保护某物免受危险或威胁的过程和达到的状态。 资讯安全是一门通过安全控制保护资讯...