写在最后
本次我的分享也接近尾声了,感谢你们在百忙中花上一下午来这里聆听我的宣讲,希望在接下来的日子,我们共同成长,一起进步!!!
最后放上一个大概的Android学习方向及思路(详细的内容太多了~),提供给大家:
对于程序员来说,要学习的知识内容、技术有太多太多,这里就先放上一部分,其他的内容有机会在后面的文章向大家呈现出来,不过我自己所有的学习资料都整理成了一个文档,一直在不断学习,希望能帮助到大家,也节省大家在网上搜索资料的时间来学习,也可以分享动态给身边好友一起学习!
为什么某些人会一直比你优秀,是因为他本身就很优秀还一直在持续努力变得更优秀,而你是不是还在满足于现状内心在窃喜!希望读到这的您能点个小赞和关注下我,以后还会更新技术干货,谢谢您的支持!
Android架构师之路很漫长,一起共勉吧!
如果你觉得文章写得不错就给个赞呗?如果你觉得那里值得改进的,请给我留言,一定会认真查询,修正不足,谢谢。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
NotificationChannel(
NOTIFICATION_CHANNEL_ID,
NOTIFICATION_CHANNEL_NAME,
NotificationManager.IMPORTANCE_HIGH
)
notificationManager.createNotificationChannel(mNotificationChannel)
}
notificationBuilder
.setSmallIcon(R.mipmap.logo)
.setLargeIcon(
bitmap ?: BitmapFactory.decodeResource(
context,
R.mipmap.logo
)
)
.setContentTitle(title)
.setContentText(body)
.setShowWhen(true)
.setAutoCancel(true)
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
//设置为全屏通知, 此时若App处于前台, 会为悬挂通知, 无论前台后台, 都会自动启动Acitivity
.setFullScreenIntent(pendingIntent, true)
.setContentIntent(pendingIntent)
notificationManager.notify(
requestCode /* ID of notification */,
notificationBuilder.build()
)
bitmap?.recycle()
}
}
java:
private void sendNotification(String title, String body, PushMessageNode data, Bitmap bitmap) {
Intent intent = new Intent(this, PushJumpActivity.class);
intent.putExtra(WhatConstants.Intent.INSTANCE.getFIRE_PUSH_MESSAGE(), data);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
int requestCode = (int) (Math.random() * 1000) + 1;
PendingIntent pendingIntent = PendingIntent.getActivity(this, requestCode /* Request code */, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationManager notificationManager = null;
notificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
Notification.Builder notificationBuilder;
if (notificationManager != null) {
if (Build.VERSION.SDK_INT >= 26) {
NotificationChannel mNotificationChannel = new NotificationChannel(“1”, “Channel1”, NotificationManager.IMPORTANCE_HIGH);
notificationManager.createNotificationChannel(mNotificationChannel);
notificationBuilder = new Notification.Builder(this, “1”);
} else {
notificationBuilder = new Notification.Builder(this);
}
notificationBuilder = notificationBuilder
.setSmallIcon(R.mipmap.logo)
.setLargeIcon(bitmap != null ? bitmap : BitmapFactory.decodeResource(context.getResources(), R.mipmap.logo))
.setContentTitle(title)
.setContentText(body)
.setShowWhen(true)
.setPriority(Notification.PRIORITY_HIGH)
.setAutoCancel(true)
.setSound(defaultSoundUri)
//设置为全屏通知, 此时若App处于前台, 会为悬挂通知, 无论前台后台, 都会自动启动Acitivity
.setFullScreenIntent(pendingIntent, true);
.setContentIntent(pendingIntent);
notificationManager.notify(requestCode /* ID of notification */, notificationBuilder.build());
if (bitmap != null)
bitmap.recycle();
}
}
获取剪贴板数据
说明: 只有默认输入法(IME)或者是目前处于焦点的应用, 才能访问到剪贴板数据.
这也就是说应用已经不能在后台监听剪贴板数据了, 不过我对目前处于焦点的应用这句话不太了解 . 另外在适配过程中, 遇到了一个问题, 在Acitivity onCreate直接获取剪贴板数据是不能成功获取的, 而在按钮点击的时候是可以的:
class SimpleActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//直接获取剪切板数据
getTextFromClip()
//剪贴板有数据也return “”
//点击按钮获取剪切板数据
view.setOnClickListener {
getClipboardData()
//返回剪贴板的正常数据
}
}
private fun getTextFromClip(): String {
val clipboardManager =
context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager?
if (null == clipboardManager || !clipboardManager.hasPrimaryClip()) {
return “”
}
val clipData = clipboardManager.primaryClip
if (null == clipData || clipData.itemCount < 1) {
return “”
}
val clipText = clipData.getItemAt(0)?.text ?: “”
return clipText.toString()
}
}
后面又对目前处于焦点的应用思考了一下, 应该就是视图加载到窗口上才能获取焦点, 后面经过适配, 在view.post()之后获取剪贴板数据,又参考了这篇文章[Android源码解析]view.post()到底干了啥, 了解到view.post()是在view dispatchAttachedToWindow后执行的, 然后写出方法如下:
kotlin:
/**
- 获取剪贴板的内容
*/
fun getClipBoardText(@Nullable activity: Activity?, f: (String) -> Unit) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && activity != null) {
getTextFromClipFroAndroidQ(activity, f)
} else {
f.invoke(getTextFromClip())
}
}
/**
- AndroidQ 获取剪贴板的内容
*/
@TargetApi(Build.VERSION_CODES.Q)
private fun getTextFromClipFroAndroidQ(@NonNull activity: Activity, f: (String) -> Unit) {
val runnable = Runnable {
try {
val clipboardManager =
activity.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager?
if (null == clipboardManager || !clipboardManager.hasPrimaryClip()) {
f.invoke(“”)
return@Runnable
}
val clipData = clipboardManager.primaryClip
if (null == clipData || clipData.itemCount < 1) {
f.invoke(“”)
return@Runnable
}
val clipText = clipData.getItemAt(0)?.text ?: “”
f.invoke(clipText.toString())
return@Runnable
} catch (e: Exception) {
f.invoke(“”)
return@Runnable
}
}
activity.registerActivityLifecycleCallbacks(object :Application.ActivityLifecycleCallbacks {
override fun onActivityPaused(activity: Activity) {
}
override fun onActivityStarted(activity: Activity) {
}
override fun onActivityDestroyed(activity: Activity) {
activity.window?.decorView?.removeCallbacks(runnable)
}
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {
}
override fun onActivityStopped(activity: Activity) {
}
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
}
override fun onActivityResumed(activity: Activity) {
}
})
activity.window?.decorView?.post(runnable) ?: f.invoke(“”)
}
private fun getTextFromClip(): String {
try {
//可以使用Application的Context
val clipboardManager =
context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager?
if (null == clipboardManager || !clipboardManager.hasPrimaryClip()) {
return “”
}
val clipData = clipboardManager.primaryClip
if (null == clipData || clipData.itemCount < 1) {
return “”
}
val item = clipData.getItemAt(0) ?: return “”
val clipText = item.text ?: “”
return if (TextUtils.isEmpty(clipText)) “” else clipText.toString()
} catch (e: Exception) {
return “”
}
}
java:
public interface Function {
/** Invokes the function. */
void invoke(String text);
}
void getClipBoardText(@Nullable Activity activity, final Function f) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && activity != null) {
getTextFromClipFroAndroidQ(activity, f);
} else {
f.invoke(getTextFromClip());
}
}
/**
- AndroidQ 获取剪贴板的内容
*/
@TargetApi(Build.VERSION_CODES.Q)
private void getTextFroClipFromAndroidQ(@NonNull final Activity activity, final Function f) {
Runnable runnable = new Runnable() {
@Override
public void run() {
ClipboardManager clipboardManager =
(ClipboardManager)activity.getSystemService(Context.CLIPBOARD_SERVICE);
if (null == clipboardManager || !clipboardManager.hasPrimaryClip()) {
f.invoke(“”);
return;
}
ClipData clipData = clipboardManager.getPrimaryClip();
if (null == clipData || clipData.getItemCount() < 1) {
f.invoke(“”);
return;
}
ClipData.Item item = clipData.getItemAt(0);
if (item == null) {
f.invoke(“”);
return;
}
CharSequence clipText = item.getText();
if (TextUtils.isEmpty(clipText))
f.invoke(“”);
else
f.invoke(clipText.toString());
}
}
activity.registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(@NonNull Activity activity, @androidx.annotation.Nullable Bundle savedInstanceState) {
}
@Override
public void onActivityStarted(@NonNull Activity activity) {
}
@Override
public void onActivityResumed(@NonNull Activity activity) {
}
@Override
public void onActivityPaused(@NonNull Activity activity) {
}
@Override
public void onActivityStopped(@NonNull Activity activity) {
}
@Override
public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) {
}
@Override
public void onActivityDestroyed(@NonNull Activity activity) {
activity.getWindow().getDecorView().removeCallbacks(runnable);
}
});
activity.getWindow().getDecorView().post(runnable);
}
private String getTextFromClip() {
ClipboardManager clipboardManager =
(ClipboardManager)context.getSystemService(Context.CLIPBOARD_SERVICE);
if (null == clipboardManager || !clipboardManager.hasPrimaryClip()) {
return “”;
}
ClipData clipData = clipboardManager.getPrimaryClip();
if (null == clipData || clipData.getItemCount() < 1) {
return “”;
}
ClipData.Item item = clipData.getItemAt(0);
if (item == null)
return “”;
CharSequence clipText = item.getText();
if (TextUtils.isEmpty(clipText))
return “”;
else
return clipText.toString();
}
最后
针对Android程序员,我这边给大家整理了一些资料,包括不限于高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter等全方面的Android进阶实践技术;希望能帮助到大家,也节省大家在网上搜索资料的时间来学习,也可以分享动态给身边好友一起学习!
-
Android前沿技术大纲
-
全套体系化高级架构视频
Android高级架构资料、源码、笔记、视频。高级UI、性能优化、架构师课程、混合式开发(ReactNative+Weex)全方面的Android进阶实践技术,群内还有技术大牛一起讨论交流解决问题。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
1715875415889)]
Android高级架构资料、源码、笔记、视频。高级UI、性能优化、架构师课程、混合式开发(ReactNative+Weex)全方面的Android进阶实践技术,群内还有技术大牛一起讨论交流解决问题。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!