Showing posts with label android. Show all posts
Showing posts with label android. Show all posts

Wednesday, July 3, 2019

Android OpenGL ES Setting for Build up

To generate more powerful graphic effect, OpenGL ES(OpenGL for Embeded System) provides modern graphic processing api.

I will make a simple GLSurfaceView(pre-defined view class to use opengl in android) and Renderer to visualize effect only using fragment shader. Once I build this successfully, I can refer some interesting glsl codes in online like glsl sandbox or shader frog.

1. Manifest Setting

I will use gles 3.1 version. Way to checking of supported version is in developer docs.

<uses-feature android:glEsVersion="0x00030001" android:required="true" />
<application ... />

2. Custom GLSurfaceView Class

class MySurfaceView(context:Context) :GLSurfaceView(context) {
  private lateinit var renderer:MyRenderer
override fun setRenderer(renderer: Renderer) {
   super.setRenderer(renderer)
   this.renderer = renderer as MyRenderer
 }
}

3. Custom Renderer

Most of Renderer's codes are boilerplate code. Shader compile and attach processes are explained in dev docs. I will add tiny additional code.

class MyRenderer(context:Context):GLSurfaceView.Renderer{
 ...
 private var hMouse = 0
 private var hTime = 0
 private var hResolution = 0
 private var width = 0
 private var height = 0
 var mouseX : Float = 0f
 var mouseY : Float = 0f
 ...
 override fun onDrawFrame(gl: GL10?) {
  ...
  GLES31.glClear(GLES31.GL_DEPTH_BUFFER_BIT or GLES31.GL_COLOR_BUFFER_BIT)
  val time = SystemClock.uptimeMillis() % 10000L
  GLES31.glUniform1f(hTime,(time/1000f))
  GLES31.glUniform2f(hResolution,this.width.toFloat(),this.height.toFloat())
  GLES31.glUniform2f(hMouse,-1f+(2*this.mouseX/this.width),1f-(2*this.mouseY/this.height))
  GLES31.glUniformMatrix4fv(hScale,1,false, mScale,0)
  ...
 }
 override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
  ...
  this.width = width
  this.height = height
  ...
 }
 override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
  ...
  hTime = GLES31.glGetUniformLocation(hProgram,"time")
  hResolution = GLES31.glGetUniformLocation(hProgram,"resolution")
  hMouse = GLES31.glGetUniformLocation(hProgram,"mouse")
  ...
 }

Almost done. Override onTouchEvent in view class to pass the mouse location to renderer(mouseX,mouseY variables at above code).

override fun onTouchEvent(event: MotionEvent): Boolean {
  this.renderer.mouseX = event.x
  this.renderer.mouseY = event.y
  return super.onTouchEvent(event)
 }

4. etc

For vertex Shader, Any shape is possible. To see the fragment shader code's effect fully, use Square Shape.

And find some code in online, test and make own code.

Tuesday, June 25, 2019

Grid UI Launcher by ConstraintLayout

When we are trying to build a custom launcher, we could think about some layout options like grid, scroll view... In this post, we are implementing the grid layout by android default constraint layout.

1. Draw GuideLines

constraintlayout with grid guideline

ConstraintLayout containing 5x4 grid with 6x5 guideline

guideline attribute percent

Set constraint like the above picture(percent 0.2, 0.4, etc...) to each of vertical, horizontal lines.

2. Grid Element View

Make Custom Element View composed of upper-side Icon image, lower-side app name.

class AppIconView(context:Context) : View(context) {
 private val paint = Paint()
 private val iconDrawRegion = Rect()
 private lateinit var label: String
 lateinit var icon: Bitmap
 lateinit var packageName: String

 init{
  paint.setTypeface(Typeface.create(Typeface.DEFAULT,Typeface.NORMAL))
  paint.setAntiAlias(true)
 }

 fun setAppInfo(packageName:String, label:String ,icon:BitmapDrawable){
  this.packageName = packageName
  this.label = label
  this.icon = icon.bitmap
 }

 override fun onDraw(canvas: Canvas) {
  paint.textSize = width/7f
  val paddingW = width/5
  iconDrawRegion.set(paddingW,paddingW,width-paddingW,width-paddingW)
  canvas.drawBitmap(icon,null,iconDrawRegion,paint)

  val textDrawSize = paint.measureText(label)
  canvas.drawText(label,(width-textDrawSize)/2f,height-(2*paint.textSize),paint)
 }

Above code would make a view seems like simple and conventional launcher. For launcher's other behaviors such as drag and drop, We need some additional code that would also be covered by later post.

3. Compose Simple Activity

 guideLineV = arrayOf(R.id.guide_v0,R.id.guide_v1,R.id.guide_v2,R.id.guide_v3,R.id.guide_v4)  guideLineH = arrayOf(R.id.guide_h0,R.id.guide_h1,R.id.guide_h2,R.id.guide_h3,R.id.guide_h4,R.id.guide_h5)  layout = findViewById(R.id.my_constraint_layout)
 var app_count =0
 val filter = Intent(Intent.ACTION_MAIN)
 filter.addCategory(Intent.CATEGORY_LAUNCHER)
 val allApps = packageManager.queryIntentActivities(filter, 0)
 val cs = ConstraintSet()
 for (info in allApps) {
  val da = AppIconView(this).apply {
   id = View.generateViewId()
   setAppInfo(info.activityInfo.packageName, info.loadLabel(packageManager).toString() ,info.activityInfo.loadIcon(packageManager) as BitmapDrawable)
   
  val col = app_count % 4
  val row = app_count / 4
  if(row>4){ // Because we didn't implement tab for multiple appPage, exceeded apps would be just skipped
   break
  }
  apps[row][col] = da
  da.col = col
  da.row = row
  layout.addView(da)
  cs.connect(da.id,ConstraintSet.START,guideLineV[col],ConstraintSet.START)
  cs.connect(da.id,ConstraintSet.END,guideLineV[col+1],ConstraintSet.START)
  cs.connect(da.id,ConstraintSet.TOP,guideLineH[row],ConstraintSet.TOP)
  cs.connect(da.id,ConstraintSet.BOTTOM,guideLineH[row+1],ConstraintSet.TOP)
  app_count++
 }
 cs.applyTo(layout)

I referenced this article for getting installed apps for custom launcher. We can insert above code to oncreate method, and it's done.

4. Result

Now, Our view would be seems like below.

android launcher grid layout

Friday, June 14, 2019

When you delete project in android studio by mistake

Few minutes ago, I had almost been dying after deleting my project by mistake, I tried some third-party recovery softwares. Though it had restored some files(.gitignore, .class, etc..), really most-helpful files(in my case, kotlin files) were not recovered.

Luckily, I found a solution before shutdown the android studio then it saved me to recover the complete project with all files.

If you delete a project in android studio and are still remaining the studio open, you can recover your project.

On Menubar, VCS -> Local History -> Show History.

Then window like below picture would be shown.

how to recover misdelete by android studio history

(Because I had deleted the project after creating new-project, In history it was recorded as EXTERNAL CHANGE)

Right-click the log, and click revert. it's done.

I hope it would save you.

Saturday, June 8, 2019

Way to call Default Launcher by Custom Launcher

It would not be guaranteed to work always properly, though it works well in my case

1. manifest example

<activity ... android:label="@string/app_name" android:name=".activities.LauncherActivity" android:theme="@style/FullscreenTheme">
 <intent-filter>
  <action android:name="android.intent.action.MAIN"/>
  <category android:name="android.intent.category.HOME"/>
  <category android:name="android.intent.category.DEFAULT"/>
 </intent-filter>
</activity>

2. custom launcher code example

var launcher_list = packageManager.queryIntentActivities(Intent(Intent.ACTION_MAIN).apply { addCategory(Intent.CATEGORY_HOME) },0)
val name = ComponentName(
 //expecting first element of launchers be the default
 launcher_list[0].activityInfo.packageName,
 launcher_list[0].activityInfo.name
)

val i = Intent(Intent.ACTION_MAIN)
i.addCategory(Intent.CATEGORY_LAUNCHER)
i.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
i.setComponent(name)

startActivity(i)
finish()

[osx command] file or folder monitoring

1. command fswatch [file or folder to monitor] | xargs -I {} echo $(date) {} >> [log file name] ...