鸿蒙尝试(二)

环境和其它配置请看(一)

布局部分 想到哪里写到哪里了。。。

1,Text 换行显示

    ohos:multiple_lines="true"

2,鸿蒙日志

HiLogLabel label = new HiLogLabel(HiLog.LOG_APP, 0x00201, "TAG");
HiLog.warn(label, "测试", url);

微信截图_20210719113501.png

3,页面跳转 启动和传值


image.png
   Intent intent1 = new Intent();

            Operation operation = new Intent.OperationBuilder()
                    .withAction("action.pay")
                    .withDeviceId("1")
                    .withBundleName("xxx")
                    .withAbilityName("yyy")
                    .build();
            intent1.setOperation(operation);
            intent1.setParam("value", "10");
            present(new MainAbilitySlice(), intent1);

也可以启动界面
ohos.samples.backgrounddownload 是包名。。。。。。

 Intent intent = new Intent();
        Operation operation = new Intent.OperationBuilder().withDeviceId("")
            .withBundleName("ohos.samples.backgrounddownload")
            .withAbilityName("ohos.samples.backgrounddownload.AnotherAbility")
            .build();
        intent.setOperation(operation);
        startAbility(intent);

4,android 中handler 的使用,在鸿蒙里面EventHandler

private class EventHandler1 extends EventHandler {

        private EventHandler1(EventRunner runner) {
            super(runner);
        }

        @Override
        public void processEvent(InnerEvent event) {
            switch (event.eventId) {
                case 100:
                    /*获取参数*/
                    Object object = event.object;
                    Object param = event.param;
                    getUITaskDispatcher().asyncDispatch(() ->{

                    });
                    break;
            }
        }
    }
private void initHandler() {
        EventHandler1 handler1 = new EventHandler1(EventRunner.create("EventHandler1"));
        /*普通发送*/
        handler1.sendEvent(100);
        InnerEvent normalInnerEvent = InnerEvent.get(EVENT_MESSAGE_NORMAL, 10, "hello");
        /*普通 选择参数发送*/
        handler1.sendEvent(normalInnerEvent, EventHandler.Priority.IMMEDIATE);
        /*延时发送*/
        handler1.sendEvent(normalInnerEvent, 1000, EventHandler.Priority.IMMEDIATE);

        Runnable task1 = () -> {
            getUITaskDispatcher().asyncDispatch(() -> {
                resultText.setText(stringBuffer.toString());

            });
        };
        /*post 一个runable*/
        handler1.postTask(task1, EventHandler.Priority.IMMEDIATE);
        /*post 延时 发送一个runable*/
        handler1.postTask(task1, 1000, EventHandler.Priority.IMMEDIATE);

    }

5,异步处理。
三种情况
1,globalTaskDispatcher.syncDispatch(() -> stringBuffer.append("Sync task1 run" + System.lineSeparator()));最常见
2,中有添加一个多少时间后处理。

globalTaskDispatcher.delayDispatch(() -> {
            stringBuffer.append("DelayDispatch task1 run" + System.lineSeparator());
            final long actualDelayMs = System.currentTimeMillis() - callTime;
            stringBuffer.append("ActualDelayTime >= delayTime : " + (actualDelayMs >= DELAY_TIME));
            handler.postSyncTask(() -> resultText.setText(stringBuffer.toString()));
        }, DELAY_TIME);

3,

 TaskDispatcher dispatcher = createParallelTaskDispatcher("", TaskPriority.DEFAULT);
 Group group = dispatcher.createDispatchGroup();

Group 的使用。这个可以有多个异步条件进行。

6,线程池的使用
ThreadPoolExecutor

创建

public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {
        throw new RuntimeException("Stub!");
    }

传入runable就可以了

private static ThreadPoolExecutor executor = new ThreadPoolExecutor(CORE_COUNT, THREAD_COUNT, KEEP_ALIVE,
        TimeUnit.SECONDS, new ArrayBlockingQueue<>(WORK_QUEUE_SIZE), new CommonThreadFactory());
 
    /**
     * Submit task to execute
     *
     * @param task runnable task
     */
    public static void submit(Runnable task) {
        executor.submit(task);
    }

7,网络请求
官方请求方式

URL url = new URL(inputText.getText());
                URLConnection urlConnection = url.openConnection();
                if (urlConnection instanceof HttpURLConnection) {
                    HttpURLConnection connection = (HttpURLConnection)urlConnection;
                    connection.connect();
                    if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                        ImageSource.SourceOptions srcOpts = new ImageSource.SourceOptions();
                        ImageSource imageSource = ImageSource.create(connection.getInputStream(), srcOpts);
                        PixelMap pixelMap = imageSource.createPixelmap(null);
                        getUITaskDispatcher().syncDispatch(() -> image.setPixelMap(pixelMap));
                    }
                    connection.disconnect();
                }

这个需要线程里面进行。

这边没有真机,测试机里面是华为内部网络。
鸿蒙里面多了一个HttpResponseCache。
// 初始化时设置缓存目录dir及最大缓存空间
HttpResponseCache.install(dir, 10 * 1024 * 1024);

// 访问URL

// 为确保缓存保存到文件系统可以执行flush操作
HttpResponseCache.getInstalled().flush();

// 结束时关闭缓存
HttpResponseCache.getInstalled().close();

8,DatagramSocket 这个使用
通过Socket绑定来进行数据传输
发送

 private void netRequest(Component component) {
        ThreadPoolUtil.submit(() -> {
            NetManager netManager = NetManager.getInstance(null);
            if (!netManager.hasDefaultNet()) {
                return;
            }
            try (DatagramSocket socket = new DatagramSocket()) {
                NetHandle netHandle = netManager.getDefaultNet();
                InetAddress address = netHandle.getByName(inputText.getText());
                netHandle.bindSocket(socket);
                byte[] buffer = "I'm from Client".getBytes();
                DatagramPacket request = new DatagramPacket(buffer, buffer.length, address, PORT);
                socket.send(request);
            } catch (IOException e) {
                HiLog.error(LABEL_LOG, "%{public}s", "netRequest IOException");
            }
        });
    }

接受。是服务器端

private void startServer(Component component) {
        ThreadPoolUtil.submit(() -> {
            try (DatagramSocket socket = new DatagramSocket(PORT)) {
                DatagramPacket packet = new DatagramPacket(new byte[255], 255);
                while (true) {
                    socket.receive(packet);
                    getUITaskDispatcher().syncDispatch(() -> {
                        outText.setText(
                            "Receive a message from :" + packet.getAddress().getHostAddress() + System.lineSeparator()
                                + " on port " + packet.getPort() + System.lineSeparator() + "message :" + new String(
                                packet.getData()).substring(0, packet.getLength()));
                    });
                    packet.setLength(255);
                    Thread.sleep(1000);
                }
            } catch (IOException | InterruptedException e) {
                HiLog.error(LABEL_LOG, "%{public}s", "StartServer  IOException | InterruptedException");
            }
        });
    }

9,鸿蒙里面的服务。这个和android 就不一样了。。

  • 基于 Service 模板的 Ability(以下简称 "Service")主要用于后台运行任务(如执行音乐播放、文件下载等),但不提供用户交互界面。

    Service 可由其他应用或 Ability 启动,即使用户切换到其他应用,Service 仍将在后台继续运行。
    例如下载。
    方式1.界面启动了,后台进行下载,不耽误你做任何事情。app 挂了,或界面关闭了,下载停止。
    这种是AbilityConnection 连接,还不适于服务的一种吧。

public class DownloadServiceConnection implements IAbilityConnection {
 @Override
    public void onAbilityConnectDone(ElementName elementName, IRemoteObject iRemoteObject, int resultCode) {
        LogUtil.info(TAG, "on Ability Connect Done");
        sendHandlerMessage("service connect done");
        downloadServiceProxy = new DownloadServiceProxy(iRemoteObject);
    }
}
他会有两个方法,连接成功和连接失败两个方法。
下载方法在代理里面进行

private class DownloadServiceProxy implements IRemoteBroker {
下载方法在这个里面进行

}

通过handle 进行消息发送,在通过自己写接口进行回调。

鸿蒙里面有个下载接口。 还可以多下载进行。

方式2.
主app 切换其他app 不受影响。
启动

 private void startLocalService(String bundleName, String serviceName) {
        Intent localServiceIntent = getLocalServiceIntent(bundleName, serviceName);
        startAbility(localServiceIntent);
    }

    private void startRemoteService(String bundleName, String serviceName) {
        Intent remoteServiceIntent = getRemoteServiceIntent(bundleName, serviceName);
        startAbility(remoteServiceIntent);
    }

    private Intent getLocalServiceIntent(String bundleName, String serviceName) {
        Operation operation = new Intent.OperationBuilder().withDeviceId("")
            .withBundleName(bundleName)
            .withAbilityName(serviceName)
            .build();
        Intent intent = new Intent();
        intent.setOperation(operation);
        return intent;
    }

/**
 * LocalServiceAbility
 */
public class LocalServiceAbility extends Ability {
    private static final String TAG = MainAbilitySlice.class.getSimpleName();
    private static final HiLogLabel LABEL_LOG = new HiLogLabel(3, 0xD000F00, TAG);

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        HiLog.info(LABEL_LOG, "%{public}s",  "onStart");
        showTips(this, "LocalService onStart");
    }

    @Override
    public void onCommand(Intent intent, boolean restart, int startId) {
        super.onCommand(intent, restart, startId);
        HiLog.info(LABEL_LOG, "%{public}s",  "onCommand");
        showTips(this, "LocalService onCommand");
    }

    @Override
    public IRemoteObject onConnect(Intent intent) {
        showTips(LocalServiceAbility.this, "LocalService onConnect ");
        return new CurrentRemoteObject();
    }

    @Override
    public void onDisconnect(Intent intent) {
        super.onDisconnect(intent);
        showTips(LocalServiceAbility.this, "LocalService onDisconnect ");
    }

    @Override
    public void onStop() {
        super.onStop();
        showTips(this, "LocalService onStop");
    }

    private class CurrentRemoteObject extends RemoteObject {
        private CurrentRemoteObject() {
            super("CurrentRemoteObject");
        }

        @Override
        public boolean onRemoteRequest(int code, MessageParcel data, MessageParcel reply, MessageOption option) {
            HiLog.info(LABEL_LOG, "%{public}s",  "onRemoteRequest ");
            return true;
        }
    }

    private void showTips(Context context, String msg) {
        new ToastDialog(context).setText(msg).show();
    }
}

获取

   private IAbilityConnection connection = new IAbilityConnection() {
        @Override
        public void onAbilityConnectDone(ElementName elementName, IRemoteObject iRemoteObject, int resultCode) {
            HiLog.info(LABEL_LOG, "%{public}s", "onAbilityConnectDone resultCode : " + resultCode);
            eventHandler.sendEvent(EVENT_ABILITY_CONNECT_DONE);
            RemoteAgentProxy remoteAgentProxy = new RemoteAgentProxy(iRemoteObject);
            try {
                remoteAgentProxy.setRemoteObject("This param from client");
            } catch (RemoteException e) {
                HiLog.error(LABEL_LOG, "%{public}s", "onAbilityConnectDone RemoteException");
            }
        }

        @Override
        public void onAbilityDisconnectDone(ElementName elementName, int resultCode) {
            HiLog.info(LABEL_LOG, "%{public}s", "onAbilityDisconnectDone resultCode : " + resultCode);
            eventHandler.sendEvent(EVENT_ABILITY_DISCONNECT_DONE);
        }
    };

eventHandler这里显得就很重要了。

server需要配置cofig中配置

"abilities": [         
               {    
                   "name": ".ServiceAbility",
                   "type": "service",
                   "visible": true
                   ...
               }
           ]
  1. toast 的使用
    new ToastDialog(context).setText(msg).show();

11,也需要 权限申请

private void requestPermission() {
        if (verifySelfPermission(SystemPermission.DISTRIBUTED_DATASYNC) != IBundleManager.PERMISSION_GRANTED) {
            requestPermissionsFromUser(new String[] {SystemPermission.DISTRIBUTED_DATASYNC}, 0);
        }
    }

    @Override
    public void onRequestPermissionsFromUserResult(int requestCode, String[] permissions, int[] grantResults) {
        if (permissions == null || permissions.length == 0 || grantResults == null || grantResults.length == 0) {
            return;
        }
        if (requestCode == 0) {
            if (grantResults[0] == IBundleManager.PERMISSION_DENIED) {
                terminateAbility();
            }
        }
    }

几种现象,demo有时候连接不到虚拟机,有时候点击没有反应。身边没有真测试机用。需要重新连接。需要模拟器,还得实名认证。当然打包也需要在华为后台配置和下载签名。。。这个就麻烦了。