项目目录结构图:
目录:
1. 项目 build.gradle---查看项目主要涉及到哪些第三方库
2. 将Html文本转换成能正常显示的
3. 启动定时服务
一、项目 build.gradle—查看项目主要涉及到哪些第三方库
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
testCompile 'junit:junit:4.12'
compile 'org.jsoup:jsoup:1.9.2'
compile 'com.android.support:cardview-v7:24.0.0'
compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
// MaterialDesignDialog
compile 'com.lb:materialdesigndialog:1.0.1'
// lb封装的工具库
compile 'com.lb:utils:1.0.2'
// nohttp 网络请求框架
compile 'com.yolanda.nohttp:nohttp:1.0.0'
// 点赞
compile 'com.sackcentury:shinebutton:0.1.2'
}
二、将Html文本转换成能正常显示的Text
String desc = Html.fromHtml(englishBean.getDesc()).toString();
三、启动定时服务
1. 清单文件注册:
// 注册service
<service android:name=".service.TimingTaskService" />
// 静态注册接收器
<receiver
android:name=".receiver.TimingTaskReceiver"
android:exported="true">
<intent-filter android:priority="999">
<action android:name="com.lb.wecharenglish.getRemoteData" />
</intent-filter>
</receiver>
2、在MainActivity 中启动服务:
Intent service = new Intent(mContext, TimingTaskService.class);
startService(service);
3、定时任务 TimingTaskService:
* 类描述:后台定时任务,每隔一段时间请求网络数据<br>
*/
public class TimingTaskService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
timingTask(this);
return super.onStartCommand(intent, flags, startId);
}
private void timingTask(Context context) {
Intent intent = new Intent(getPackageName() + ".getRemoteData");
PendingIntent sender = PendingIntent.getBroadcast(context,
0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
// Schedule the alarm!
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 8);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
// 间隔时间
int interval = 1000 * 60 * 60 * 4; // 4h
// setRepeating(int type,long startTime,long intervalTime,PendingIntent pi);
am.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
interval, sender);
}
}
// 关于系统服务提醒器 http://blog.youkuaiyun.com/wangxingwu_314/article/details/8060312
4、接收器开一个工作线程执行耗时网络操作
public class TimingTaskReceiver extends BroadcastReceiver {
@Override
public void onReceive(final Context context, Intent intent) {
LogUtil.e(this, "接收到广播");
String action = intent.getAction();
if ((context.getPackageName() + ".getRemoteData").equals(action)) {
new Thread() {
@Override
public void run() {
// 获取远端数据
List<EnglishBean> remoteDatas = new EnglishServer().getDataFromRemote();
// 遍历并添加到数据库
for (EnglishBean bean : remoteDatas) {
// 查询数据库是否包含该条数据
EnglishBean dbBean = new EnglishServer().findById(context, bean.getId());
if (null == dbBean) {
// 需要发出状态栏通知
LogUtil.e(this, "显示通知");
showNewNotification(context);
}
// 添加进数据库操作
new EnglishServer().add(context, bean);
}
}
}.start();
} else {
LogUtil.e(this, "action 不一致");
LogUtil.e(this, "action=" + action);
}
}
/**
* 状态栏显示一条新通知
* @param context 上下文对象
*/
private void showNewNotification(Context context, int id, EnglishBean bean) {
// 使用通知推送消息
Notification.Builder builder = new Notification.Builder(context);
// 设置消息属性
// 必须设置的属性:小图标 标题 内容
builder.setSmallIcon(R.mipmap.ic_launcher);
builder.setContentTitle(bean.getTitle());
// noinspection deprecation
builder.setContentText(Html.fromHtml(bean.getDesc()));
//创建一个通知对象
Notification notification = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
notification = builder.build();
}
// 使用通知管理器发送一条通知
NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
manager.notify(id, notification);
}
}
四、加载图片相关配置
//设置启动图片,使用ImageLoader 防止内存溢出
ImageLoader.getInstance().displayImage("drawable://" + R.drawable.splash_pic,
iv_splash_pic, ImageLoaderOptions.fadein_options);
//延迟3秒进入主页面
mHandler.sendEmptyMessageDelayed(ENTER_HOME, 3 * 1000);
/**
* 显示图片的所有配置
* @return
*/
private DisplayImageOptions getWholeOptions() {
DisplayImageOptions options = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.loading) //设置图片在下载期间显示的图片
.showImageForEmptyUri(R.drawable.ic_launcher)//设置图片Uri为空或是错误的时候显示的图片
.showImageOnFail(R.drawable.error) //设置图片加载/解码过程中错误时候显示的图片
.cacheInMemory(true)//设置下载的图片是否缓存在内存中
.cacheOnDisk(true)//设置下载的图片是否缓存在SD卡中
.considerExifParams(true) //是否考虑JPEG图像EXIF参数(旋转,翻转)
.imageScaleType(ImageScaleType.IN_SAMPLE_INT)//设置图片以如何的编码方式显示
.bitmapConfig(Bitmap.Config.RGB_565)//设置图片的解码类型
//.decodingOptions(BitmapFactory.Options decodingOptions)//设置图片的解码配置
.delayBeforeLoading(0)//int delayInMillis为你设置的下载前的延迟时间
//设置图片加入缓存前,对bitmap进行设置
//.preProcessor(BitmapProcessor preProcessor)
.resetViewBeforeLoading(true)//设置图片在下载前是否重置,复位
.displayer(new RoundedBitmapDisplayer(20))//不推荐用!!!!是否设置为圆角,弧度为多少
.displayer(new FadeInBitmapDisplayer(100))//是否图片加载好后渐入的动画时间,可能会出现闪动
.build();//构建完成
return options;
}
//图片加载方式
displayer(BitmapDisplayer displayer) // 设置图片的显示方式,如:
.displayer(new FadeInBitmapDisplayer(100))
其中,displayer的选择值:
RoundedBitmapDisplayer(int roundPixels)设置圆角图片,不推荐!!!
FakeBitmapDisplayer()这个类什么都没做
FadeInBitmapDisplayer(int durationMillis)设置图片渐显的时间
SimpleBitmapDisplayer()正常显示一张图片
//图片加载时监听
imageLoader.displayImage(imageUrl, imageView, options, new ImageLoadingListener() {
@Override
public void onLoadingStarted() {
//开始加载的时候执行 }
@Override
public void onLoadingFailed(FailReason failReason) {
//加载失败的时候执行 }
@Override
public void onLoadingComplete(Bitmap loadedImage) {
//加载成功的时候执行 }
@Override
public void onLoadingCancelled() {
//加载取消的时候执行
}});
//避免内存泄漏
@Override
protected void onDestroy() {
mHandler.removeCallbacksAndMessages(null);
super.onDestroy();
}
五、设置apk 生成方式
applicationVariants.all { variant ->
variant.outputs.each { output ->
def oldFile = output.outputFile
// edian_channel_01_v1.1.6_360手机助手
//1.创建 edian_v
def firstName = "everyday_v";
//3.获取清单文件中的版本号
def versionName = versionName;
//4.根基标示渠道号填写对应的渠道商店
//5.构建类型 是否是debug等
def buildType = "";
if (variant.buildType.name.equals('release')) {
buildType = "release_";
} else if (variant.buildType.name.equals('debug')) {
buildType = "debug_";
}
def releaseApkName = buildType + firstName + versionName + '.apk'
// + "_" + getDate()
output.outputFile = new File(oldFile.parent as File, releaseApkName)
}
}
六、播放网络音频
final MediaPlayer player = new MediaPlayer();
player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
player.start();
}
});
try {
player.setDataSource("https://mp.weixin.qq.com/cgi-bin/readtemplate?t=tmpl/audio_tmpl&name=132&play_length=04:31");
} catch (Exception e) {
e.printStackTrace();
}
player.prepareAsync();
七、使用noHttp 网络框架建立下载任务
private DownloadRequest downloadRequest;
@SuppressLint("HandlerLeak")
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case START_DOWNLOAD:
pb_setting_synchronousing.setVisibility(View.VISIBLE);
break;
case DOWNLOAD_FINISH:
pb_setting_synchronousing.setVisibility(View.GONE);
break;
}
}
};
downloadRequest = NoHttp.createDownloadRequest(url, filePath, fileName, true, false);
// what 区分下载
// downloadRequest 下载请求对象
// downloadListener 下载监听
NoHttp.newDownloadQueue(2).add(0, downloadRequest, new DownloadListener() {
@Override
public void onDownloadError(int what, Exception exception) {
LogUtil.log(this, exception);
mHandler.sendEmptyMessage(DOWNLOAD_FINISH);
ToastUtil.showShortToast(mContext, "同步远程数据库失败,请重试");
}
@Override
public void onStart(int what, boolean isResume, long rangeSize, Headers responseHeaders, long allCount) {
LogUtil.log(this, "开始下载");
mHandler.sendEmptyMessage(START_DOWNLOAD);
}
@Override
public void onProgress(int what, int progress, long fileCount) {
// 更新下载进度
}
@Override
public void onFinish(int what, String filePath) {
//下载完成,打开数据库
SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(filePath, null);
final int count = new EnglishServer().copyDataFromDatabas(mContext, db);
db.close();
//删除已经下载的数据
File file = new File(filePath);
//noinspection ResultOfMethodCallIgnored
file.delete();
ToastUtil.showShortToast(mContext, "更新了" + count + "条数据");
mHandler.sendEmptyMessage(DOWNLOAD_FINISH);
}
@Override
public void onCancel(int what) {
LogUtil.log(this, "下载取消");
pb_setting_synchronousing.setVisibility(View.GONE);
}
});
感谢作者的分享。项目地址:https://github.com/291700351/WeCharEnglish