If you are annoyed that "Sources for Android 26" are not yet available via SDK manager, this might be for you:
- Collect source files
mkdir android-sdk-source-build
cd android-sdk-source-build
mkdir -p frameworks/base
// based on: https://github.com/george-steel/android-utils/blob/master/src/org/oshkimaadziig/george/androidutils/SpanFormatter.java | |
public class StringSpan { | |
private static final Pattern PATTERN = Pattern.compile("%([^a-zA-z%]*)([[a-zA-Z%]&&[^tT]]|[tT][a-zA-Z])"); | |
private StringSpan() { | |
} | |
public static CharSequence format(@NonNull CharSequence format, Object... args) { | |
return format(Locale.getDefault(), format, args); |
public class SupportVersion { | |
private SupportVersion() { | |
} | |
public static boolean isLollipopOrAbove() { | |
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP; | |
} | |
public static boolean isMarshmallowOrAbove() { | |
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M; |
If you are annoyed that "Sources for Android 26" are not yet available via SDK manager, this might be for you:
mkdir android-sdk-source-build
cd android-sdk-source-build
mkdir -p frameworks/base
#!/bin/bash | |
SOURCE=$1 | |
if [[ -z $SOURCE ]]; then | |
echo "Usage: $0 [source]" >&2 | |
exit | |
fi | |
sudo mkdir -p /mnt/sd1 |
abstract class BaseActivity<MODEL : BaseModel<Bundle>, VIEW : BaseView, out PRESENTER : BasePresenter<MODEL, VIEW>> : KoinActivity() { | |
protected abstract val presenter: PRESENTER | |
override fun onCreate(savedInstanceState: Bundle?) { | |
super.onCreate(savedInstanceState) | |
val arguments = (javaClass.genericSuperclass as ParameterizedType).actualTypeArguments | |
val model = Class.forName(arguments.first().javaClass.toString().split(" ").last()).newInstance() | |
presenter.bind(model as MODEL, this as VIEW) | |
} |
# change resolution | |
ffmpeg -i video_1920.mp4 -vf scale=300:534 video_300.mp4 | |
# convert | |
ffmpeg -i video_300.mp4 final.gif |
class ClearableAutoCompleteTextView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, | |
defStyleAttr: Int = android.R.attr.editTextStyle) | |
: AutoCompleteTextView(context, attrs, defStyleAttr) { | |
private val clearDrawable: Drawable? = ContextCompat.getDrawable(context, R.drawable.ic_clear) | |
init { | |
clearDrawable?.setBounds(0, 0, clearDrawable.intrinsicWidth, clearDrawable.intrinsicHeight) | |
setOnTouchListener { _, event -> | |
if (isClearDrawableVisible() && event.action == MotionEvent.ACTION_UP) { |
inline fun TextView.textWatcher(init: CustomTextWatcher.() -> Unit) = addTextChangedListener(CustomTextWatcher().apply(init)) | |
@Suppress("unused") | |
class CustomTextWatcher : TextWatcher { | |
private var _beforeTextChanged: ((CharSequence?, Int, Int, Int) -> Unit)? = null | |
private var _onTextChanged: ((CharSequence?, Int, Int, Int) -> Unit)? = null | |
private var _afterTextChanged: ((Editable?) -> Unit)? = null | |
private var _beforeTextChangedShout: (() -> Unit)? = null | |
private var _onTextChangedShout: (() -> Unit)? = null |
object Bus { | |
// val event = Event<Any>() | |
} | |
class Event<TYPE> { | |
private val handlers = arrayListOf<((TYPE) -> Unit)>() | |
operator fun plusAssign(handler: (TYPE) -> Unit) { | |
handlers.add(handler) | |
} |
fun String.encodeBase64ToString(): String = String(this.toByteArray().encodeBase64()) | |
fun String.encodeBase64ToByteArray(): ByteArray = this.toByteArray().encodeBase64() | |
fun ByteArray.encodeBase64ToString(): String = String(this.encodeBase64()) | |
fun String.decodeBase64(): String = String(this.toByteArray().decodeBase64()) | |
fun String.decodeBase64ToByteArray(): ByteArray = this.toByteArray().decodeBase64() | |
fun ByteArray.decodeBase64ToString(): String = String(this.decodeBase64()) | |
fun ByteArray.encodeBase64(): ByteArray { | |
val table = (CharRange('A', 'Z') + CharRange('a', 'z') + CharRange('0', '9') + '+' + '/').toCharArray() |