未知账号

明天的一切都是未知的!


  • 首页

  • 归档

  • 标签

修改包名

发表于 2017-06-19

修改包名可以采用包名替换的方式:

public class PackageUtil {

    public static String orgPackageName1="com.zcdog.smartlocker.android";
    public static String orgPackageName2="com.zcdog.zchat";

    public static String destPackageName1="com.wangwang.tv.android";
    public static String destPackageName2="com.wangwang.zchat";

    public static String packageReplace(String className){
        if (className!=null&&!className.isEmpty()){
            if (className.contains(orgPackageName1)){
                return className.replaceAll(orgPackageName1,destPackageName1);
            }
            if (className.contains(orgPackageName2)){
                return className.replaceAll(orgPackageName2,destPackageName2);
            }
        }
        return className;
    }
}

Intent 新方式

发表于 2017-06-19

Intent 新方式

可以避免在传值的时候如果前后命名不统一出现的问题:

Class A extends Activity(){

        public static Intent newIntent(Context context,String url,String title) {
            Map<String,String> queryParameters=new LinkedHashMap<>();
            queryParameters.put(UrlConstant.USER_ID,"");
            queryParameters.put(UrlConstant.DEVICE_ID, "");
            url= UrlUtils.splitJoint(url,queryParameters);
            Bundle bundle=new Bundle();
            bundle.putString(A.WEB_VIEW_BUNDLE_TITLE,title);
            bundle.putString(A.WEB_VIEW_BUNDLE_LOAD_URL, url);
            Intent intent=new Intent(context, A.class);
            intent.putExtra(A.WEBVIEW_BUNDLE_NAME,bundle);
            return intent;
        }
    }


    Class B extends Activity{
    String incomeRuleUrl = ServiceUrlConstants.URL.getIncomeRuleUrl();
        startActivity(A.newIntent(this, incomeRuleUrl, "收益规则"));
    }

合并排序

发表于 2017-06-19

合并排序代码实现

results.add(messages + "各种东西加进去");
List<Message> mergeMsgs = new ArrayList<>();
final Queue<Message> priorityQueue = new PriorityQueue<Message>(results.size(), new MessageComparator());
final Map<String, Iterator<Message>> index = new HashMap<>();
for (List<Message> list : results) {
    Iterator<Message> iterator = list.iterator();
    Message firstMsg = iterator.next();
    index.put(firstMsg.getTargetId(), iterator);
    priorityQueue.add(firstMsg);
}

while (mergeMsgs.size() < count && !priorityQueue.isEmpty()) {
    Message tmp = priorityQueue.poll();
    mUserIdsToMsgIds.put(tmp.getTargetId(), tmp.getMessageId());
    if (tmp.getMessageDirection() != Message.MessageDirection.SEND ||
            AcccountIdentifier.isOriginUserId(tmp.getTargetId())) {
        mergeMsgs.add(tmp);
    }
    Iterator<Message> iterator = index.get(tmp.getTargetId());
    if (iterator.hasNext()) {
        priorityQueue.add(iterator.next());
    }
}

图片模糊

发表于 2017-06-19
  • 图片模糊代码:

    public class BlurBitmap {
        private static final float BITMAP_SCALE = 0.4f;
    
        private static final float BLUR_RADIUS = 25f;
    
        public static Bitmap blur(Context context, Bitmap image){
            int width = Math.round(image.getWidth() * BITMAP_SCALE);
            int height = Math.round(image.getHeight() * BITMAP_SCALE);
    
            Bitmap inputBitmap = Bitmap.createScaledBitmap(image, width, height, false);
            Bitmap outputBitmap = Bitmap.createBitmap(inputBitmap);
    
            RenderScript renderScript = RenderScript.create(context);
    
            ScriptIntrinsicBlur scriptIntrinsicBlur = ScriptIntrinsicBlur.create(renderScript, Element.U8_4(renderScript));
    
            Allocation tmpIn = Allocation.createCubemapFromBitmap(renderScript, inputBitmap);
            Allocation tmpOut = Allocation.createCubemapFromBitmap(renderScript, outputBitmap);
    
            scriptIntrinsicBlur.setRadius(BLUR_RADIUS);
            scriptIntrinsicBlur.setInput(tmpIn);
            scriptIntrinsicBlur.forEach(tmpOut);
    
            tmpOut.copyTo(outputBitmap);
    
            return outputBitmap;
        }
    }
    

NodeProgramma

发表于 2017-06-19

测试

测试副标题

列表

无序列表

  • 1
  • 2
  • 3

    有序列表

  1. one
  2. two
  3. three

引用

这是一段 别人叙述的话

插入图片

Mou icon

插入加链接

Baidu

字体

粗体

粗体文字测试

斜体

斜体文字测试

表格

这里有问题


| Tables        | Are           | Cool  |
| ------------- |:-------------:| -----:|
| col 3 is      | right-aligned | $1600 |
| col 2 is      | centered      |   $12 |
| zebra stripes | are neat      |    $1 |

dog bird cat
foo foo foo6/17/2017 3:06:08 PM

bar | bar | bar
baz | baz | baz

代码框

function hello(){

    aaa();
    console.log("hello world!");
}

hello();

分割线


Markdown编辑器快捷键:

· 加粗 Ctrl + B

· 斜体 Ctrl + I

· 引用 Ctrl + Q

· 插入链接 Ctrl + L

· 插入代码 Ctrl + K

· 插入图片 Ctrl + G

· 提升标题 Ctrl + H

· 有序列表 Ctrl + O

· 无序列表 Ctrl + U

· 横线 Ctrl + R

· 撤销 Ctrl + Z

· 重做 Ctrl + Y


开发笔记

发表于 2017-06-19

  • 正则表达式

    正则验证小于1000000且最多两位小数的正则:
    ^([1-9]\d?(.\d{1,2})?|0.\d{1,2}|1000000)$ 或者\d{6}.\d{2} 。

  • Fiddler 抓包

    用Fiddler抓包工具监控网络,并给自己的手机设置代理 查看自己电脑的IP 在 cmd中输入ipconfig 即可

  • 边界处理

    在对某个类进行操作,或者基于某个类给另一个类进行操作的时候,首先要判断要操作的那个类是否为空。

getactivity 这个方法在一个类中只有一个,所以有时候可以直接调用,不需要添加this标签。

对于某些函数中需要传递的参数,如果本类中没有该种类型,可以getInstance 也阔以尝试直接传递null替代。

  • 加载优化

    如果一个类中需要加载不同的多个界面,那么最好采用标签将其中一个界面嵌套进去,便于管理

  • 关于内存泄漏:
    开发中需要注意的点以免内存泄漏:

  • 不要让生命周期长于Activity的对象持有到Activity的引用

  • 尽量使用Application的Context而不是Activity的Context

  • 尽量不要在Activity中使用非静态内部类,因为非静态内部类会隐式持有外部类实例的引用(具体可以查看细话Java:”失效”的private修饰符了解)。如果使用静态内部类,将外部实例引用作为弱引用持有。

  • 垃圾回收不能解决内存泄露,了解Android中垃圾回收机制

  • 获取context的方法,以及使用上context和applicationContext的区别:
  • View.getContext,返回当前View对象的Context对象,通常是当前正在展示的Activity对象。

  • Activity.getApplicationContext,获取当前Activity所在的(应用)进程的Context对象,通常我们使用Context对象时,要优先考虑这个全局的进程Context。

  • ContextWrapper.getBaseContext():用来获取一个ContextWrapper进行装饰之前的Context,可以使用这个方法,这个方法在实际开发中使用并不多,也不建议使用。

  • Activity.this 返回当前的Activity实例,如果是UI控件需要使用Activity作为Context对象,但是默认的Toast实际上使用ApplicationContext也可以。

  • AccessibilityService 的相关介绍和使用
  • 介绍:AccessibilityService 可以用来自动化测试,自动抢红包,自动安装等第

广播注册

发表于 2017-06-19
  • 通用注册广播的方式:

    DateChangedBroadcastReceiver broadcastReceiver;
    broadcastReceiver=new DateChangedBroadcastReceiver();
    IntentFilter intentFilter=new IntentFilter();
    intentFilter.addAction(Intent.ACTION_DATE_CHANGED);
    BaseApplication.getContext().registerReceiver(broadcastReceiver,intentFilter);
    

批量打包

发表于 2017-06-19

批量打包

  • 首先修改manifest文件内容:

原文件:

package com.zcdog.util.info.android;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.text.TextUtils;

import java.io.IOException;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

public class ManifestUtil {
    private static final String SP_CONFIG_NAME = "channel-sp";
    private static final String SP_KEY = "channel_id";
    public static final String START_FLAG = "META-INF/channel_";

    /**
     * 获取META-INFO下面的渠道
     *
     * @param context
     * @return
     */
    public static String getChannel(Context context) {
        SharedPreferences sp = context.getSharedPreferences(SP_CONFIG_NAME, Context.MODE_PRIVATE);
        String channel = sp.getString(SP_KEY, null);
        if (!TextUtils.isEmpty(channel)) {
            return channel;
        }
        ApplicationInfo appinfo = context.getApplicationInfo();
        String sourceDir = appinfo.sourceDir;
        ZipFile zipfile = null;
        try {
            zipfile = new ZipFile(sourceDir);
            Enumeration<?> entries = zipfile.entries();
            while (entries.hasMoreElements()) {
                ZipEntry entry = ((ZipEntry) entries.nextElement());
                String entryName = entry.getName();
                if (entryName.contains(START_FLAG)) {
                    channel = entryName.replaceAll(START_FLAG, "");
                    sp.edit().putString(SP_KEY, channel).apply();
                    return channel;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (zipfile != null) {
                try {
                    zipfile.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return "";

    }
}

修改后的文件:

package com.zcdog.util.info.android;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.text.TextUtils;

import java.io.IOException;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

public class ManifestUtil {

    public static final String START_FLAG = "META-INF/channel_";
    public static final String SEPARATOR = "%";
    private static final String TAG ="ManifestUtilTag";
    public static String channel;
    public static String inviteCode="";

    /**
     * 获取META-INFO下面的渠道,如果为空,尝试获取metaData下的配置的渠道
     * @param context
     * @return
     */
    public static String getChannel(Context context) {
        if (!TextUtils.isEmpty(channel)) {
            return channel;
        }
        initMetaInfData(context);
        Logger.d(TAG,"channel=="+channel);
        return channel;
    }

    /**
     * 获取邀请码
     *
     * @param context
     * @return
     */
    public static String getInviteCode(Context context) {
        if (!TextUtils.isEmpty(inviteCode)) {
            return inviteCode;
        }
        initMetaInfData(context);
        Logger.d(TAG,"inviteCode=="+inviteCode);
        return inviteCode;
    }

    /**
     * 获取Manifest里面配置的metaData数据信息
     */
    public static String getMetaDataValue(Context context, String metaDataName) {
        String channel = "";
        try {
            channel = context.getPackageManager().getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA).metaData.getString(metaDataName);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
            channel = "UnKnown_zcdog";
        }
        return channel;
    }

    /**
     * 第一次获取META-INF/channel_的数据信息
     * @param context
     */
    private static void initMetaInfData(Context context){
        ApplicationInfo appinfo = context.getApplicationInfo();
        String sourceDir = appinfo.sourceDir;
        ZipFile zipfile = null;
        try {
            zipfile = new ZipFile(sourceDir);
            Enumeration<?> entries = zipfile.entries();
            while (entries.hasMoreElements()) {
                ZipEntry entry = ((ZipEntry) entries.nextElement());
                String entryName = entry.getName();
                if (entryName.contains(START_FLAG)) {
                    String channelAndInviteCode = entryName.replaceAll(START_FLAG, "");
                    //判断是否有邀请码
                    String[] valuesArray = channelAndInviteCode.split(SEPARATOR);
                    if (valuesArray != null && valuesArray.length > 1) {
                        channel = valuesArray[0];
                        inviteCode = valuesArray[1];
                    } else {
                        channel = channelAndInviteCode;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (zipfile != null) {
                try {
                    zipfile.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        if (TextUtils.isEmpty(channel)) {
            channel = getMetaDataValue(context, "DISTRIBUTION_CHANNEL");
        }
    }
}
  • 然后修改Python脚本:

原脚本:

import sys,os,shutil,zipfile,time
apkVersion="3.5"
apkPrefixName="Zcdog"
srcFileName=apkPrefixName+apkVersion+"_normal.apk"
apksDir="apks"
destDir=os.path.abspath('.')
target_file="channel.apk"

file=open("channels.txt")

def writeChannelToApk(filename,channel):
        z=zipfile.ZipFile(filename,'a',zipfile.ZIP_DEFLATED)
        empty_channel_file="META-INF/channel_{channe}".format(channe=channel)
        if not os.path.exists(target_file):
            open(target_file,'a').close()
        z.write(target_file,empty_channel_file)
        z.close()
        print "writeChannelToApkchannel"+channel+","+filename+"\n"

def cpFile(srcPath,fileName):
    destPath = destDir + os.path.sep + fileName
    if os.path.exists(srcPath) and not os.path.exists(destPath):
        shutil.copy(srcPath,destPath)



if not os.path.exists(srcFileName):
    print "source file "+srcFileName+" not exists"
    sys.exit(1)


start = time.clock()

if not os.path.exists(apksDir):
    os.makedirs(apksDir)

for line in file:
    channel=line.strip('\n').strip()
    targetFileName=apksDir+"/"+apkPrefixName+apkVersion+"_"+channel+".apk"
    print "copyfile:"+targetFileName
    cpFile(srcFileName,targetFileName)
    writeChannelToApk(targetFileName,channel)
end = time.clock()

print("The function run time is : %.03f seconds" %(end-start))


#heliao-app-91-5.1.1

修改后的脚本:

import sys,os,shutil,zipfile,time
apkVersion="3.5"
apkPrefixName="Zcdog"
srcFileName=apkPrefixName+apkVersion+"_normal.apk"
apksDir="apks"
destDir=os.path.abspath('.')
target_file="channel.apk"
separator="%";
file=open("channels.txt")

def writeChannelToApk(filename,channel):
        z=zipfile.ZipFile(filename,'a',zipfile.ZIP_DEFLATED)
        empty_channel_file="META-INF/channel_{channe}".format(channe=channel)
        if not os.path.exists(target_file):
            open(target_file,'a').close()
        z.write(target_file,empty_channel_file)
        z.close()
        print "writeChannelToApkchannel"+channel+","+filename+"\n"

def cpFile(srcPath,fileName):
    destPath = destDir + os.path.sep + fileName
    if os.path.exists(srcPath) and not os.path.exists(destPath):
        shutil.copy(srcPath,destPath)



if not os.path.exists(srcFileName):
    sys.exit(1)


start = time.clock()

if os.path.exists(apksDir):
    shutil.rmtree(apksDir)
    os.makedirs(apksDir)
else:
    os.makedirs(apksDir)


for line in file:
    channelAndInviteCode=line.strip('\n').strip()
    channel=channelAndInviteCode.split(separator)[0]
    print "channel_name=="+channel
    targetFileName=apksDir+"/"+apkPrefixName+apkVersion+"_"+channel+".apk"
    print "copyfile:"+targetFileName
    cpFile(srcFileName,targetFileName)
    writeChannelToApk(targetFileName,channelAndInviteCode)
end = time.clock()

print("The function run time is : %.03f seconds" %(end-start))


#heliao-app-91-5.1.1

修改之前读取邀请码的函数:

//读取配置文件的当前渠道对应的邀请码
    AssetManager assetManager= BaseApplication.getContext().getAssets();
    InputStream ins=null;
    try {
        ins=assetManager.open("channel.properties");
        Properties properties=new Properties();
        properties.load(ins);
        String chanelName= Misc.getChannelValue();
        String inviteCode=properties.getProperty(chanelName);
        Logger.d(TAG, "inviteCode" + inviteCode + ":chanelName==" + chanelName);
        if(inviteCode!=null&&!inviteCode.isEmpty()){
            et_invite_code.setText(inviteCode);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }finally {
       if (ins!=null){
           try {
               ins.close();
           } catch (IOException e) {
               e.printStackTrace();
           }
       }
    }

修改之后获取邀请码的函数:

//读取配置文件的当前渠道对应的邀请码
   String inviteCode = ManifestUtil.getInviteCode(BaseApplication.getContext());
   if (!TextUtils.isEmpty(inviteCode)) {
       et_invite_code.setText(inviteCode);
   }

日历

发表于 2017-06-19
  • 设置闹钟提醒

    在Android 4.4 以后,为节省电池耗电等,不再使用一个重复闹钟,而是使用多个单次闹钟,当前一个闹钟到点提醒以后,再次设置下一个闹钟。

获取日历的当前时间

public Date getStartTime(String startTime){
     Date startDate = DateUtil.tFormat8(startTime);
     Calendar calendar=Calendar.getInstance();
     calendar.setTime(startDate);
     Date nowDate = DateUtil.nowDate(BaseApplication.getContext());
     Calendar nowCalendar = Calendar.getInstance();
     nowCalendar.setTime(nowDate);
     calendar.set(Calendar.YEAR, nowCalendar.get(Calendar.YEAR));
     calendar.set(Calendar.MONTH, nowCalendar.get(Calendar.MONTH));
     calendar.set(Calendar.DAY_OF_MONTH, nowCalendar.get(Calendar.DAY_OF_MONTH));
     return calendar.getTime();
}

####判断某个日期的所属的星座
public class ConstellationUtil{
private final static int[] dayArr = new int[]{20, 19, 21, 20, 21, 22, 23, 23, 23, 24, 23, 22};
private final static String[] constellationArr = new String[]{ “摩羯座”, “水瓶座”, “双鱼座”, “白羊座”, “金牛座”, “双子座”, “巨蟹座”, “狮子座”, “处女座”, “天秤座”, “天蝎座”, “射手座”, “摩羯座”};

    public static String getConstellation(int month, int day){
        return day < dayArr[month - 1] ? constellationArr[month - 1] : constellationArr[month];
    }

    public static getConstellation(Date date){
        if(date == null)
            return "";
        Calendar canlendar = Calendar.getInstance();
        canlendar.setTime(date);
        int month = canlendar.get(Calendar.MONTH) + 1;
        int day = canlendar.get(Calendar.DAY_OF_MONTH);

        return getConstellation(month, day);
    }
}

Retrofit

发表于 2017-06-19

Retrofit 网络请求协议:

在 Retrofit 整个网络请求参数主要分成 : scheme, authority, path, query, header, body 六块 。
其中authority可以进一步划分为:host:port
示例:host:www.java2s.com : port: 8080

  • 在整个结构中,将scheme 和 authority 这两者的合体称为 baseurl ,接口方法如下:

    Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://api.github.com/")
        .build();
    
  • header 分为两种

第一种,静态header:又分为 a: 单个键值对注解 和 b: 多个键值对注解

第二种:动态header : 又分为 a: 局部动态header(分为单个键值对和多个键值对) 和 b: 全局动态header(适用于项目中的header规则一致的情况)

  • 这里采用 OKHttp 的 interceptor 作例:

    private static void initHttpClient(){
        OKHttpClient.Builder httpClientBuilder = new OKHttpClient.Builder();
        if(httpClientBuilder.interceptors() != null){
            httpClientBuilder.interceptors().clear();
        }
    
        httpClientBuilder.addInterceptor(new Interceptor(){
            @Override
            public Response intercept(Chain chain) throws IOException{
    
                //这里可以获取到请求的request 所有的数据
    
                Request request = chain.request();
                String path = request.url().encodedPath();
                String query = request.url().query();
    
                Request interRequest = chain.request().newBuilder()
                    .headers(Headers.of(Map yourHeader))
                    .build();
    
                return chain.proceed(interRequest);
            }
        })
        .connectTimeout(10, TimeUnit.SECONDS)
        .readTimeout(10, TimeUnit.SECONDS);
    
        mOkHttpClient = httpClientBuilder.build();
    }
    
  • 构建Retrofit 实例:

    public static Retrofit retrofit(){
        if(mRetrofit == null){
            initHttpClient();
            mRetrofit = new Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .client(mOKHttpClient)
                    .addConvertFactory(GsonConvertFactory.create())
                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                    .builder();
        }
        return mRetrofit;
    }
    
1234
HM

HM

懂的or不懂的,我都记录在这里

36 日志
3 标签
GitHub Twitter Weibo DouBan ZhiHu FriendLink
© 2017 HM
由 Hexo 强力驱动
主题 - NexT.Muse