0%

原文:http://toptulip.iteye.com/blog/780309 使用php加密字符串,生成密文,java解析密文还原字符串. Java的部分直接复制调不通,改了下,下面的代码是能正常运行的。 php:

<?php
class DES
{
    var $key;
    var $iv; //偏移量

    function DES($key, $iv=0)
    {
        $this->key = $key;
        if($iv == 0)
        {
            $this->iv = $key;
        }
        else 
        {
            $this->iv = $iv;
        }
    }

    //加密
    function encrypt($str)
    {		
        $size = mcrypt_get_block_size ( MCRYPT_DES, MCRYPT_MODE_CBC );
        $str = $this->pkcs5Pad ( $str, $size );
        
        $data=mcrypt_cbc(MCRYPT_DES, $this->key, $str, MCRYPT_ENCRYPT, $this->iv);
        //$data=strtoupper(bin2hex($data)); //返回大写十六进制字符串
        return base64_encode($data);
    }
    
    //解密
    function decrypt($str)
    {
        $str = base64_decode ($str);
        //$strBin = $this->hex2bin( strtolower($str));
        $str = mcrypt_cbc(MCRYPT_DES, $this->key, $str, MCRYPT_DECRYPT, $this->iv );
        $str = $this->pkcs5Unpad( $str );
        return $str;
    }

    function hex2bin($hexData)
    {
        $binData = "";
        for($i = 0; $i < strlen ( $hexData ); $i += 2)
        {
            $binData .= chr(hexdec(substr($hexData, $i, 2)));
        }
        return $binData;
    }

    function pkcs5Pad($text, $blocksize)
    {
        $pad = $blocksize - (strlen ( $text ) % $blocksize);
        return $text . str_repeat ( chr ( $pad ), $pad );
    }

    function pkcs5Unpad($text)
    {
        $pad = ord ( $text {strlen ( $text ) - 1} );
        if ($pad > strlen ( $text ))
            return false;
        if (strspn ( $text, chr ( $pad ), strlen ( $text ) - $pad ) != $pad)
            return false;
        return substr ( $text, 0, - 1 * $pad );
    }
}
$str = 'abcd';
$key= 'asdfwef5';
$crypt = new DES($key);
$mstr = $crypt->encrypt($str);
$str = $crypt->decrypt($mstr);

echo  $str.' <=> '.$mstr;

?>

java:

package com.test;

import it.sauronsoftware.base64.Base64;

import java.security.Key;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;

import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;

public class Main
{
    public static final String ALGORITHM_DES = "DES/CBC/PKCS5Padding";
    /**
     * DES算法,加密
     *
     * @param data 待加密字符串
     * @param key  加密私钥,长度不能够小于8位
     * @return 加密后的字节数组,一般结合Base64编码使用
     * @throws CryptException 异常
     */
    public static String encode(String key,String data) throws Exception
    {
        return encode(key, data.getBytes());
    }
    /**
     * DES算法,加密
     *
     * @param data 待加密字符串
     * @param key  加密私钥,长度不能够小于8位
     * @return 加密后的字节数组,一般结合Base64编码使用
     * @throws CryptException 异常
     */
    public static String encode(String key,byte[] data) throws Exception
    {
        try
        {
        	DESKeySpec dks = new DESKeySpec(key.getBytes());
        	
        	SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            //key的长度不能够小于8位字节
            Key secretKey = keyFactory.generateSecret(dks);
            Cipher cipher = Cipher.getInstance(ALGORITHM_DES);
            IvParameterSpec iv = new IvParameterSpec(key.getBytes());
            AlgorithmParameterSpec paramSpec = iv;
            cipher.init(Cipher.ENCRYPT_MODE, secretKey,paramSpec);
            
            byte[] bytes = cipher.doFinal(data);
            

//            return byte2hex(bytes);
            return new String(Base64.encode(bytes));
        } catch (Exception e)
        {
            throw new Exception(e);
        }
    }

    /**
     * DES算法,解密
     *
     * @param data 待解密字符串
     * @param key  解密私钥,长度不能够小于8位
     * @return 解密后的字节数组
     * @throws Exception 异常
     */
    public static byte[] decode(String key,byte[] data) throws Exception
    {
        try
        {
            SecureRandom sr = new SecureRandom();
        	DESKeySpec dks = new DESKeySpec(key.getBytes());
        	SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            //key的长度不能够小于8位字节
            Key secretKey = keyFactory.generateSecret(dks);
            Cipher cipher = Cipher.getInstance(ALGORITHM_DES);
            IvParameterSpec iv = new IvParameterSpec(key.getBytes());
            AlgorithmParameterSpec paramSpec = iv;
            cipher.init(Cipher.DECRYPT_MODE, secretKey,paramSpec);
            return cipher.doFinal(data);
        } catch (Exception e)
        {
            throw new Exception(e);
        }
    }
    
    /**
     * 获取编码后的值
     * @param key
     * @param data
     * @return
     * @throws Exception
     */
    public static String decodeValue(String key,String data) 
    {
        byte[] datas;
        String value = null;
        try {

        		datas = decode(key, Base64.decode(data.getBytes()));
            
            value = new String(datas);
        } catch (Exception e) {
            value = "";
        }
        return value;
    }

    public static void main(String[] args) throws Exception
    {
        System.out.println("明:abcd ;密:" + Main.encode("asdfwef5","abcd"));
    }
}

美工设计的EditText是灰色边框,内部颜色渐变的,为了适应不同的高宽度,我这采用xml定义一个shape做背景。 edit_text_bg.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
    <!-- 边缘线的宽度和颜色 -->
    <stroke android:width="1px" android:color="#969696" />
    <!-- 中间渐变,角度0从左往右,正值为逆时针,270度为从上到下 -->
    <gradient  android:startColor="#ffffff" android:centerColor="#e9e9e9" android:endColor="#d8d8d8" android:angle="270"/>
    <!-- 设置四个角的角度 -->
   <corners android:topLeftRadius="5dp" android:topRightRadius="5dp" android:bottomLeftRadius="5dp" android:bottomRightRadius="5dp"/>
   <!-- 设置padding -->
   <padding android:left="10dp" android:top="10dp" android:right="10dp" android:bottom="10dp"/>
</shape>

使用时,设置EditText的background属性为drawable/edit_text_bg即可

Java中的MessageDigest.diges方法可以传入一个byte数组计算摘要,返回一个byte数组,但php中没有相应的方法,md5只能传入一个字符串参数,且默认返回的计算完的string,但md5方法可传入一个bool参数,返回原始的16位2进制数据。

$raw_md5=unpack("c*", md5($orign,true));

unpack方法用指定的格式解包返回数组,这里返回的就是byte数组。

NSUserDefaults类似android中的SharedPreferences,可以把数据持久化到设备中。

//
//  ViewController.h
//  Data
//
//  Created by 方 海鹏 on 12-10-28.
//  Copyright (c) 2012年 方 海鹏. All rights reserved.
//

#import 

@interface ViewController : UIViewController
@property (strong, nonatomic) IBOutlet UILabel *label;
@property (strong,nonatomic) NSUserDefaults *userDefaults;
- (IBAction)read:(id)sender;
- (IBAction)write:(id)sender;

@end




//
//  ViewController.m
//  Data
//
//  Created by 方 海鹏 on 12-10-28.
//  Copyright (c) 2012年 方 海鹏. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    _userDefaults=[NSUserDefaults standardUserDefaults];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
    _userDefaults=nil;
}
/*
 读
 */
- (IBAction)read:(id)sender {
    
    NSString *string=[_userDefaults valueForKey:@"string"];
    _label.text=string;
    
    
}
/*
 写
 */
- (IBAction)write:(id)sender {
    [_userDefaults setObject:@"保存" forKey:@"string"];
    [_userDefaults synchronize];
}
@end

RadioButton是单选按钮,N个RadioButton从属于一个RadioGroup,一个RadioGroup中,只有一个RadioButton是可以被选中的。 Gallery里,可以用RadioGroup指示当前播放的是第几张,效果如下图: 实现过程: 准备两张图片,一张是选中时,一张未选中,在Drawable下定义一个gallery_indicator.xml:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
    <item android:state_checked="true" android:drawable="@drawable/galleryfocus"></item>
    <item android:state_checked="false" android:drawable="@drawable/galleryunfocus"></item>
</selector>

在布局文件中调用:

<RadioGroup
        android:id="@+id/indicator"
        android:layout_width="fill_parent"
        android:layout_height="20dp"
        android:layout_alignBottom="@+id/gallery"
        android:gravity="center"
        android:orientation="horizontal" >

        <RadioButton
            android:id="@+id/rb0"
            android:layout_width="6dp"
            android:layout_height="6dp"
            android:layout_marginRight="3dp"
            android:background="@drawable/gallery_indicator"
            android:button="@null"
            android:checked="true" />

        <RadioButton
            android:id="@+id/rb1"
            android:layout_width="6dp"
            android:layout_height="6dp"
            android:layout_marginRight="3dp"
            android:background="@drawable/gallery_indicator"
            android:button="@null"
            android:checked="false" />

        <RadioButton
            android:id="@+id/rb2"
            android:layout_width="6dp"
            android:layout_height="6dp"
            android:layout_marginRight="3dp"
            android:background="@drawable/gallery_indicator"
            android:button="@null"
            android:checked="false" />

        <RadioButton
            android:id="@+id/rb3"
            android:layout_width="6dp"
            android:layout_height="6dp"
            android:layout_marginRight="3dp"
            android:background="@drawable/gallery_indicator"
            android:button="@null"
            android:checked="false" />

        <RadioButton
            android:id="@+id/rb4"
            android:layout_width="6dp"
            android:layout_height="6dp"
            android:layout_marginRight="3dp"
            android:background="@drawable/gallery_indicator"
            android:button="@null"
            android:checked="false" />

        <RadioButton
            android:id="@+id/rb5"
            android:layout_width="6dp"
            android:layout_height="6dp"
            android:layout_marginRight="3dp"
            android:background="@drawable/gallery_indicator"
            android:button="@null"
            android:checked="false" />

        <RadioButton
            android:id="@+id/rb6"
            android:layout_width="6dp"
            android:layout_height="6dp"
            android:layout_marginRight="3dp"
            android:background="@drawable/gallery_indicator"
            android:button="@null"
            android:checked="false" />

        <RadioButton
            android:id="@+id/rb7"
            android:layout_width="6dp"
            android:layout_height="6dp"
            android:layout_marginRight="3dp"
            android:background="@drawable/gallery_indicator"
            android:button="@null"
            android:checked="false" />

        <RadioButton
            android:id="@+id/rb8"
            android:layout_width="6dp"
            android:layout_height="6dp"
            android:layout_marginRight="3dp"
            android:background="@drawable/gallery_indicator"
            android:button="@null"
            android:checked="false" />

        <RadioButton
            android:id="@+id/rb9"
            android:layout_width="6dp"
            android:layout_height="6dp"
            android:layout_marginRight="3dp"
            android:background="@drawable/gallery_indicator"
            android:button="@null"
            android:checked="false" />
    </RadioGroup>

RadioButton的button属性必须为null,背景为刚才定义的xml文件,id分别是rb0到rb9,后面设置选中项时有用。 这里提一下,用java代码把button属性设为null的方式是:button.setButtonDrawable(android.R.color.transparent);即设为透明色 设置选中项,因为Gallery的OnItemSelectedListener得到的是一个int型的position,我们需要根据这个position确定选中项的id,就是刚刚在xml中定义的rb0-rb9。两种方法: 1、switch(position). 2、反射。 因为有十项,如果用switch,代码量会很多,这里用反射。

                //这里用了无限循环的Gallery,但真正的图片只有10张,所以除10取余确定真实的图片位置
                int realPosition=position%10;
                String idStr="rb"+realPosition;
                
                R.id ids=new R.id();
                Field field;
                try {
                    field = R.id.class.getField(idStr);
                    int resId=(Integer)field.get(ids);
                    mainActivity.indicator.check(resId);
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } 

下面是再来个稍微复杂一点的例子: 整个控件宽度不固定,文本在左边,图片在右边,自适应不同分辨率不同宽度。 这里需要我们自己定义一个类继承自RadioButton,在onLayout方法里计算控件的宽度,文本占据的宽度,以及图片占据的宽度,再根据上面的几个宽度计算文本与图片的间距。

import android.app.Activity;
import android.content.Context;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.widget.RadioButton;

public class CustomRadioButton extends RadioButton {
    Activity activity;
    public CustomRadioButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
        activity=(Activity)context;
        
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        // TODO Auto-generated method stub
        super.onLayout(changed, left, top, right, bottom);
        //把dp转换成px
        DisplayMetrics dm=new DisplayMetrics();
        activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
        Paint paint = new Paint();
        paint.setTextSize(16f*dm.density);// 设置字符大小
        
        int textWidth = (int) paint.measureText(this.getText(), 0, getText().length());
        Drawable drawableRight=this.getCompoundDrawables()[2];
        this.setCompoundDrawablePadding(getWidth()-textWidth-drawableRight.getIntrinsicWidth());
    }

}

xml中调用:

<cn.xxx.xxx.view.CustomCheckBox
        android:layout_width="fill_parent"
        android:layout_height="60dp"
        android:textColor="@color/black"
        android:textSize="16dp"
        android:background="#00000000"
        android:text="我时代城风水师的寺村地"
        android:button="@null"
        android:drawableRight="@drawable/from_radiogroup" />

drawableRight定义的是一个selector。background是透明的,没加background,在文本左边会多出几个像素的间距,暂时没找到原因。

说明:下面的例子使用了AndroidAnnotation,并非标准的开发模式,但是几行重要代码都是相同的。 这个例子是一个按钮,外层是LinearLayout,垂直布局,里面是一个ImageView,一个TextView,需要添加自定义的属性,以支持在Xml中写入ImageView的图片和TextView的文字。 先声明属性: `添加values/attrs.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MainTabButton">
        <attr name="src" format="reference"></attr>
        <attr name="text" format="string|reference"></attr>
    </declare-styleable>
</resources>

声明了两个属性,一个src,限制值为引用,一个text,限制值为字符串或引用. format其他可能的值: reference:引用其他资源 color:颜色 boolean:布尔 dimension:尺寸 float:浮点 integer:整数 string:字符串 fraction:百分比 enum:枚举,用法:

       <attr name="language">
            <enum name="English" value="1"/>
        </attr>

flag:位或运算,用法

<attr name="windowSoftInputMode">
        <flag name="stateUnspecified" value="1" />
        <flag name = "adjustNothing" value = "0x30" />
        </attr>

<activity android:windowSoftInputMode="stateUnspecified | adjustNothing">

添加完属性后,写相应的类: MainTabButton.java:

package com.pocketdigi.components;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.googlecode.androidannotations.annotations.AfterViews;
import com.googlecode.androidannotations.annotations.EViewGroup;
import com.googlecode.androidannotations.annotations.ViewById;
import com.pocketdigi.dayday.R;

@EViewGroup(R.layout.component_button)
public class MainTabButton extends LinearLayout {
    @ViewById
    ImageView imageView;
    @ViewById
    TextView textView;
    int imageId;
    String text;
    public MainTabButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
        TypedArray a = context.obtainStyledAttributes(attrs,
                R.styleable.MainTabButton);
        //读取XML中设置的属性值
        imageId=a.getResourceId(R.styleable.MainTabButton_src, R.drawable.tab_radio_channel_normal);
        text=a.getString(R.styleable.MainTabButton_text);
        a.recycle();
    }
    //视图载入后,再设置两个控件
    @AfterViews
    public void afterViews()
    {
        setImage(imageId);
        setText(text);
    }

    public void setImage(int resId) {
        imageView.setImageResource(resId);
    }

    public void setText(String text) {
        textView.setText(text);
    }
    //选中方法,如果选中,显示另一张图片,并改变文字颜色
    public void selected(boolean isSelected)
    {
        if(isSelected)
        {
            switch(imageId)
            {
            case R.drawable.tab_radio_home_normal:
                setImage(R.drawable.tab_radio_home_selected);
                textView.setTextColor(getResources().getColor(R.color.tab_text_selected));
                break;
            case R.drawable.tab_radio_channel_normal:
                setImage(R.drawable.tab_radio_channel_selected);
                textView.setTextColor(getResources().getColor(R.color.tab_text_selected));
                break;
            case R.drawable.tab_radio_download_normal:
                setImage(R.drawable.tab_radio_download_selected);
                textView.setTextColor(getResources().getColor(R.color.tab_text_selected));
                break;
            case R.drawable.tab_radio_search_normal:
                setImage(R.drawable.tab_radio_search_selected);
                textView.setTextColor(getResources().getColor(R.color.tab_text_selected));
                break;
            case R.drawable.tab_radio_setting_normal:
                setImage(R.drawable.tab_radio_setting_selected);
                textView.setTextColor(getResources().getColor(R.color.tab_text_selected_blue));
                break;
            }
        }
    }

}

XML中使用:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:dayday="http://schemas.android.com/apk/res/com.pocketdigi.dayday"
    android:layout_width="fill_parent"
    android:layout_height="50dp"
    android:layout_gravity="center"
    android:background="@drawable/tab_bg"
    android:gravity="center"
    android:orientation="horizontal"
    android:weightSum="5" >

    <com.pocketdigi.components.MainTabButton_
        android:id="@+id/home"
        android:layout_width="0dp"
        android:layout_height="fill_parent"
        android:layout_weight="1"
        android:paddingLeft="10dp"
        dayday:src="@drawable/tab_radio_home_normal"
        dayday:text="首页" >
    </com.pocketdigi.components.MainTabButton_>
</LinearLayout>`

原理:UIViewController中的- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender方法,会在场景切换前被调用,在该方法中设置指定的属性作为传递到下一个场景的参数,在下一场景中,通过presentingViewController属性,可以得到切换到该场景的前一个场景的实例,然后再读取前面设置的属性,实现数据的传送。 假设ViewController传送到SecondViewController: 下面的代码段都略去了无关代码。 ViewController.h,添加属性:

@property (strong,nonatomic) NSString *string;

ViewController.m:

@synthesize string;

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
//设置属性 
   string=@"asdfasfd";
    [super prepareForSegue:segue sender:sender];
}

SecondViewController.h:

//因为要引用ViewController实例,所以必须导入ViewController.h
#import "ViewController.h"

SecondViewController.m:

 ViewController *viewController=(ViewController *)self.presentingViewController;
//读取
  NSString *string=viewController.string;

假设A跳转到B,三种方法: 1.按住ctrl键,拖动A上的控件(比如说UIButton)到B上,弹出菜单,选择Modal.不需要写任何代码,在A上点击Button就会跳转到B 2. 按住ctrl键,拖动A上的View Controller到B上,弹出菜单,选择Modal,两个场景间自动添加连接线和图标,选中该图标,打开Storyboard Segue,identifier输入一个标识符,这里以”aaaa”为例.A里需要跳转时,执行下面的代码:

 [self performSegueWithIdentifier:@"aaaa" sender:self];

3.完全用代码来实现,代码如下:

    //先获取UIStoryBoard对象,参数为文件名
    UIStoryboard *mainStoryBoard=[UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
    //获取SecondViewController实例,参数是StoryBoard ID,选中View Controller,在Identity Inspector中
    SecondViewController *second=[mainStoryBoard instantiateViewControllerWithIdentifier:@"second"];
    //设置过渡的样式,和显示的样式
    second.modalTransitionStyle=UIModalTransitionStyleFlipHorizontal;
    second.modalPresentationStyle=UIModalPresentationFormSheet;
    //显示
    [self presentViewController:second animated:YES completion:nil];

System Sound Services只能播放不越过30秒的声音,且支持格式只有wav,没有提供操纵声音和控制音量的功能,一般只用于播放通知。

    SystemSoundID soundId;
    //后面将使用soundId引用音频文件
    NSString *soundFile=[[NSBundle mainBundle] pathForResource:@"aaa" ofType:@"wav"];
    //通过NSBundle的 mainBundle方法返回一个NSBundle对象,该对象对应当前应用程序可执行二进制文件所属目录。pathForResource方法获取aaa.wav的真实路径。
    AudioServicesCreateSystemSoundID((__bridge CFURLRef)[NSURL fileURLWithPath:soundFile], &soundId);
    //创建soundFile的SystemSoundID,(__bridge CFURLRef)是强制转换成CFURLRef对象,因为此处要将一个c语言的结构转换为Objective-c对象,所以必须加上__bridge
    AudioServicesPlaySystemSound(soundId);
    //播放音频 System Sound Services不能播放越过30秒的声音,且只支持wav

Objective-c中判断某对象是否为某个类的实例

- (IBAction)changeSpeed:(id)sender {
    //判断sender是不是UISlider
    if ([sender isMemberOfClass:[UISlider class]]) {
        speedStepper.value=speedSlider.value;
    }else{
        speedSlider.value=speedStepper.value;
        
    }
    speed.text=[NSString stringWithFormat:@"%f",speedSlider.value ];
}